Java 中的 Serial GC、Parallel GC、CMS、G1、ZGC 和 Shenandoah 是不同的垃圾收集器,各自基于不同的设计理念,适用于不同的应用场景。以下是它们的特点及适用场景分析:
1. Serial GC(串行垃圾收集器)
- 特点:
- 单线程执行垃圾回收,回收时会暂停所有用户线程(Stop-The-World,STW)。
- 实现简单,内存占用少,没有线程交互开销。
- 采用"标记-复制"(新生代)和"标记-整理"(老年代)算法。
- 适用场景:
- 单线程环境或客户端应用(如桌面程序)。
- 内存较小的嵌入式系统。
- 不适合服务器环境和高并发应用(STW 时间过长)。
- 启用参数:
-XX:+UseSerialGC
2. Parallel GC(并行垃圾收集器)
- 特点:
- 多线程执行垃圾回收,提高吞吐量(单位时间内处理的任务量)。
- 仍有 STW 停顿,但停顿时间比 Serial GC 短。
- 新生代采用"标记-复制",老年代采用"标记-整理"算法。
- 关注吞吐量优化,默认会根据 CPU 核心数自动调整线程数。
- 适用场景:
- 注重吞吐量的服务器应用(如后台计算、批处理任务)。
- 多核 CPU 环境,允许一定 STW 停顿。
- 不适合对响应时间敏感的应用(如 Web 服务)。
- 启用参数:
-XX:+UseParallelGC
(默认新生代并行)、-XX:+UseParallelOldGC
(老年代也并行,JDK 8 后默认启用)
3. CMS(Concurrent Mark Sweep,并发标记清除)
- 特点:
- 以低延迟为目标,尽量减少 STW 时间。
- 老年代回收主要分为 4 个阶段:初始标记(STW)→ 并发标记 → 重新标记(STW)→ 并发清除。
- 新生代仍使用 Parallel GC 的"标记-复制"算法。
- 缺点:
- 并发阶段会占用 CPU 资源,降低吞吐量。
- 采用"标记-清除"算法,会产生内存碎片。
- 对大堆内存支持不佳,可能因内存碎片导致频繁 Full GC。
- 适用场景:
- 对响应时间敏感的应用(如 Web 服务器、电商系统)。
- 堆内存中等大小(通常小于 16GB),且 CPU 核心数充足。
- 注意:JDK 9 中被标记为 deprecated,JDK 14 中移除,推荐用 G1 替代。
- 启用参数:
-XX:+UseConcMarkSweepGC
4. G1(Garbage-First)
- 特点:
- 面向大堆内存(支持数十 GB 甚至更大),兼顾吞吐量和延迟。
- 将堆内存划分为多个大小相等的 Region(区域),优先回收垃圾最多的 Region("Garbage-First")。
- 采用"标记-复制"(Region 间复制)和"标记-整理"算法,减少内存碎片。
- STW 停顿可预测,支持设置最大停顿时间目标(
-XX:MaxGCPauseMillis
)。 - 同时管理新生代和老年代,无需配合其他收集器。
- 适用场景:
- 大堆内存应用(如大型分布式系统、中间件)。
- 既要求一定吞吐量,又需要控制延迟的场景(如企业级应用)。
- 替代 CMS 的主流选择(JDK 9 后默认 GC)。
- 启用参数:
-XX:+UseG1GC
(JDK 9+ 默认)
5. ZGC(Z Garbage Collector)
- 特点:
- 超低延迟设计,STW 时间控制在毫秒级以内(通常 < 10ms),且几乎不随堆大小增长而增加。
- 支持超大堆内存(TB 级),采用基于 Region 的内存布局。
- 并发执行大部分回收阶段(标记、转移、重定位),仅初始标记和最终标记有极短 STW。
- 采用"标记-复制"算法,通过着色指针和读屏障实现高效并发操作。
- 缺点:吞吐量略低于 G1,内存开销较高(额外占用约 15-30% 堆空间)。
- 适用场景:
- 超大堆内存应用(如大型数据库、大数据处理)。
- 对延迟极端敏感的场景(如高频交易、实时响应系统)。
- 启用参数:
-XX:+UseZGC
(JDK 11 引入,JDK 15 正式可用)
6. Shenandoah
- 特点:
- 目标是低延迟,STW 时间与堆大小无关(支持 GB 到 TB 级堆)。
- 采用"标记-整理"算法,通过转发指针和读屏障实现并发压缩(无内存碎片)。
- 所有阶段(除初始标记和最终标记)均并发执行,STW 时间极短(通常 < 10ms)。
- 与 ZGC 相比,内存开销较低,但实现更复杂。
- 适用场景:
- 大堆内存且对延迟敏感的应用(如分布式服务、实时数据分析)。
- 需要平衡延迟和内存开销的场景。
- 注意:Oracle JDK 不包含 Shenandoah,主要在 OpenJDK、RedHat 等发行版中提供。
- 启用参数:
-XX:+UseShenandoahGC
(JDK 12 引入)
总结对比
收集器 | 延迟特性 | 吞吐量 | 堆大小支持 | 适用场景 | 典型应用示例 |
---|---|---|---|---|---|
Serial GC | 高延迟(STW长) | 低 | 小(<1GB) | 客户端/嵌入式 | 桌面应用、小程序 |
Parallel GC | 中延迟 | 高 | 中(<10GB) | 吞吐量优先的批处理任务 | 数据分析、后台计算 |
CMS | 低延迟(部分阶段并发) | 中 | 中(<16GB) | 响应时间敏感的中小堆应用 | 传统 Web 服务 |
G1 | 可预测延迟 | 中高 | 大(<100GB) | 平衡延迟与吞吐量的大堆应用 | 企业级应用、中间件 |
ZGC | 超低延迟 | 中 | 超大(TB级) | 超大堆+极端低延迟需求 | 高频交易、大型数据库 |
Shenandoah | 超低延迟 | 中 | 超大(TB级) | 超大堆+平衡内存开销 | 分布式服务、实时数据处理 |
选择时需根据应用的延迟需求、堆大小、CPU 资源等因素综合考量,优先推荐 G1(通用场景)、ZGC/Shenandoah(超大堆+低延迟)。