Skip to content

7 种回收器总结与调优建议

七种回收器全景对比

收集器年轻代老年代算法停顿吞吐量JDK 版本默认
SerialSerialSerial Old复制 / 标记-压缩很长1.3+-
ParNewParNewCMS复制 / 标记-清除较短1.4+CMS 默认
ThroughputPSPO复制 / 标记-压缩最高1.4+-
CMSParNewCMS复制 / 标记-清除1.5+JDK 14 移除
G1G1G1复制 / 标记-清除可预测7+JDK 9+ 默认
ZGCZGCZGC着色指针 + 并发< 1ms11+JDK 21 默认
ShenandoahSh.Sh.转发指针< 10ms12+-

收集器组合图

┌─────────────────────────────────────────────────────────┐
│                    JVM 堆                                 │
│                                                         │
│  年轻代                                                │
│  ┌──────────────────────────────────────────────────┐ │
│  │  Serial | ParNew | PS Scavenge | G1 | ZGC | Sh. │ │
│  └──────────────────────────────────────────────────┘ │
│                          │ 晋升                          │
│  老年代                                                │
│  ┌──────────────────────────────────────────────────┐ │
│  │  Serial Old | CMS | PO | G1 | ZGC | Shenandoah │ │
│  └──────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘

选型决策树

需要选择 GC 收集器?

      ├── 是否需要低延迟?(Web 服务、实时系统)
      │         │
      │         ├── 是否需要 < 1ms 停顿?
      │         │         │
      │         │         ├── 是 → ZGC(JDK 11+)
      │         │         │
      │         │         └── 否 → G1(JDK 9+ 默认)
      │         │
      │         └── 否(批处理、离线计算)
      │                   │
      │                   └── Throughput/Parallel GC

      ├── 内存很小?(< 1GB)
      │         │
      │         └── Serial

      ├── 使用 JDK 8?
      │         │
      │         └── Throughput GC(JDK 8 推荐)

      └── 不想调优?

                └── G1(JDK 9+ 默认,开箱即用)

调优建议

通用调优原则

原则说明
不要过早优化先用默认配置(JDK 9+ 默认 G1)
基于数据调优通过 GC 日志和监控数据做决策
一次只改一个参数便于定位问题
设置合理的期望GC 不是万能的,停顿和吞吐量是对立的

调优步骤

1. 开启 GC 日志
   └─ java -Xlog:gc*:file=gc.log MyApp

2. 运行一段时间,收集数据
   └─ jstat -gcutil <pid> 1000

3. 分析数据
   ├─ 吞吐量是否满足?
   ├─ 停顿时间是否可接受?
   └─ 内存使用是否合理?

4. 针对性调优
   ├─ 吞吐量不够 → 增大堆 / 使用 Throughput GC
   ├─ 停顿太长 → 使用 G1 / ZGC
   └─ 内存泄漏 → 排查泄漏点

5. 重复 2-4 直到满意

Throughput GC 调优

bash
# 目标:高吞吐量
java -Xms4g -Xmx4g \
     -XX:+UseParallelGC \
     -XX:+UseParallelOldGC \
     -XX:GCTimeRatio=19 \           # 目标吞吐量 95%
     -XX:MaxGCPauseMillis=500 \     # 最大停顿 500ms
     -XX:+UseAdaptiveSizePolicy \  # 自动调节
     MyApp

G1 调优

bash
# 目标:可预测停顿
java -Xms4g -Xmx4g \
     -XX:+UseG1GC \
     -XX:MaxGCPauseMillis=200 \    # 目标停顿 200ms
     -XX:InitiatingHeapOccupancyPercent=45 \
     MyApp

ZGC 调优

bash
# 目标:亚毫秒停顿
java -Xms16g -Xmx16g \
     -XX:+UseZGC \
     -XX:MaxGCPauseMillis=1 \
     MyApp

GC 参数速查表

场景推荐参数
标准 Web 服务-XX:+UseG1GC -XX:MaxGCPauseMillis=200
低延迟金融系统-XX:+UseZGC -XX:MaxGCPauseMillis=1
批处理/Hadoop 风格-XX:+UseParallelGC -XX:GCTimeRatio=19
大内存(> 32GB)-XX:+UseZGC -XX:MaxGCPauseMillis=5
容器/K8s-XX:+UseContainerSupport -XX:+UseG1GC
JVM 基准测试-XX:+UseEpsilonGC

常见问题与解决方案

问题原因解决方案
FullGC 频繁对象晋升太快增大 Survivor 区,降低晋升阈值
停顿时间过长GC 选择不当切换到 G1 / ZGC
内存持续增长内存泄漏排查泄漏点(dump + MAT)
吞吐量不足GC 太过频繁增大堆,使用 Parallel GC
元空间满类加载过多增大 -XX:MaxMetaspaceSize
直接内存满NIO 使用过多增大 -XX:MaxDirectMemorySize

JDK 版本与 GC 推荐

JDK 版本推荐 GC
JDK 8Throughput GC(UseParallelGC
JDK 9~10G1
JDK 11~20ZGC(低延迟)/ G1
JDK 21+ZGC(默认)

本节小结

GC 调优的本质是取舍

吞吐量和停顿时间是对立的:
  高吞吐量 → 每次 GC 多做工作 → 停顿时间更长
  低停顿   → 每次 GC 少做工作 → 吞吐量降低

没有完美的 GC,只有适合的 GC:
  批处理 → Throughput GC
  Web 服务 → G1 / ZGC
  金融交易 → ZGC
  默认选择 → G1(JDK 9~20)/ ZGC(JDK 21+)

记住:不要为了调优而调优。先用 G1(JDK 9+)或 ZGC(JDK 11+),只有在 GC 日志告诉你有问题时,才针对性地调优。

到这里,「垃圾回收器(实战)」全部完成。接下来进入最后一部分——GC 日志分析

基于 VitePress 构建