1. JVM 垃圾回收器对比选择(截至 JDK 17)
JVM 提供了多种垃圾回收器,适用于不同场景(吞吐量优先、低延迟优先、大/小堆等)。以下是所有主流 GC 的分类、特点及适用版本:
1.1. 按分代分类
JVM 堆内存通常分为 年轻代(Young Generation) 和 老年代(Old Generation),不同 GC 组合适用于不同分代:
年轻代 GC | 老年代 GC | 组合名称 | JDK 版本支持 |
---|---|---|---|
Serial | Serial Old | Serial + Serial Old | JDK 1.0+ |
ParNew | CMS | ParNew + CMS | JDK 1.4~14 |
Parallel Scavenge | Parallel Old | Parallel + Parallel | JDK 1.4+ |
G1(不分代) | G1(统一 Region 回收) | G1(独立) | JDK 7+(9+ 默认) |
ZGC / Shenandoah | (不分代) | 独立 | JDK 11+ / 12+ |
1.2. 所有垃圾回收器列表及特点
1.2.1. 串行 GC(Serial GC)
组合:Serial(年轻代) + Serial Old(老年代)
特点:单线程回收,全程 STW(Stop-The-World),适合客户端或小内存应用。
启用参数:
-XX:+UseSerialGC
适用场景:单核 CPU、小堆(<100MB)、客户端程序(如早期 Java GUI 应用)。
1.2.2. 并行 GC(Parallel GC / Throughput GC)
组合:Parallel Scavenge(年轻代) + Parallel Old(老年代)
特点:多线程并行回收,吞吐量优先,但 STW 时间较长。
启用参数:
-XX:+UseParallelGC -XX:+UseParallelOldGC
适用场景:多核 CPU、大堆(几十 GB)、批处理任务(如 Hadoop、Spark)。
1.2.3. 并发标记清除 GC(CMS)
组合:ParNew(年轻代) + CMS(老年代)
特点:低延迟优先,老年代使用并发标记-清除(减少 STW),但会产生内存碎片。
启用参数:
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC
适用场景:中小堆(<8GB)、需要低延迟的 Web 服务(JDK 8 及之前)。
注意:JDK 9 开始废弃,JDK 14 中移除,不推荐新项目使用。
1.2.4. G1(Garbage-First)
特点:
- 逻辑分代(Region 划分),平衡吞吐量和低延迟。
- 支持可预测停顿(
-XX:MaxGCPauseMillis
)。
启用参数:
-XX:+UseG1GC
适用场景:大堆(几 GB~几十 GB)、JDK 9+ 默认 GC,适合大多数服务端应用。
1.2.5. ZGC(Z Garbage Collector)
特点:
- 超低延迟(STW 通常 <1ms),支持 TB 级堆内存。
- 基于 Region 设计,并发压缩(无碎片问题)。
启用参数:
-XX:+UseZGC
适用场景:JDK 11+,需要极低延迟(如金融交易、实时系统)。
1.2.6. Shenandoah
特点:
- 类似 ZGC,低延迟,但由 Red Hat 开发(非 Oracle 官方)。
- 并发回收,停顿时间与堆大小无关。
启用参数:
-XX:+UseShenandoahGC
适用场景:JDK 12+,适合大堆且对延迟敏感的应用。
1.2.7. Epsilon(无操作 GC)
特点:
- 不回收垃圾,分配内存直到 OOM。
- 用于性能测试或短期运行任务。
启用参数:
-XX:+UseEpsilonGC
适用场景:测试 JVM 内存分配性能,或已知无垃圾产生的应用。
1.3. 如何选择垃圾回收器?
场景 | 推荐 GC | 原因 |
---|---|---|
单核/小堆 | Serial GC | 简单高效,无多线程开销。 |
高吞吐量 | Parallel GC | 多线程并行回收,适合批处理任务。 |
低延迟(JDK 8) | ParNew + CMS | 老年代并发回收,减少 STW(但已废弃)。 |
平衡吞吐/延迟 | G1 | JDK 9+ 默认,适合大多数服务端应用。 |
超低延迟(JDK 11+) | ZGC / Shenandoah | 停顿时间极短(<1ms),适合实时系统。 |
测试/短期任务 | Epsilon | 不回收垃圾,用于性能基准测试。 |
1.4. 各 GC 的 JDK 版本支持
GC 名称 | 引入版本 | 默认版本 | 移除版本 |
---|---|---|---|
Serial GC | JDK 1.0 | - | - |
Parallel GC | JDK 1.4 | JDK 1.8 | - |
CMS | JDK 1.4 | - | JDK 14 |
G1 | JDK 7 | JDK 9+ | - |
ZGC | JDK 11 | - | - |
Shenandoah | JDK 12 | - | - |
Epsilon | JDK 11 | - | - |
1.5. 总结
JDK 8 及之前:
- 吞吐量优先 → Parallel GC。
- 低延迟 → ParNew + CMS(已废弃,不建议新项目使用)。
JDK 9+:
- 默认 G1,平衡吞吐量和延迟。
- 超低延迟 → ZGC(Oracle JDK)或 Shenandoah(OpenJDK)。
特殊场景:
- 测试 → Epsilon。
- 单核/嵌入式 → Serial GC。
建议:
- 大多数生产环境使用 G1(JDK 9+)或 ZGC(超低延迟)。
- 避免使用已废弃的 CMS。