★ CMS、G1、ZGC 收集器有何区别?如何选型?

结论先行:CMS 是追求低停顿的“标记-清除”老年代收集器,JDK 9 起废弃、14 移除;G1 把整个堆划分为 Region,能提供可预测停顿,是 JDK 9+ 的默认收集器;ZGC 用染色指针与读屏障实现近无停顿并发回收,适合超大堆、毫秒级停顿场景。

三者核心差异

对比项CMSG1ZGC
内存模型分代连续空间Region 化分代Region 化不分代
核心算法标记-清除Region 间复制为主染色指针 + 读屏障
停顿目标尽量低但不保证可配置期望停顿(默认 200ms)停顿与堆大小无关,毫秒级
碎片问题明显,可触发 Concurrent Mode FailureRegion 复制缓解碎片几乎无碎片
成熟度已退役JDK 9+ 默认,最通用适合超大堆、超低延迟

选型建议

  • JDK 8 存量服务:CMS 或 G1 都可用;希望停顿更平滑就切 G1(-XX:+UseG1GC)。
  • 普通 4~16GB 堆、可接受几十毫秒停顿:G1 开箱即用,只需按需调 MaxGCPauseMillis。
  • 上百 GB 堆、要求 1~10ms 稳定停顿:选 ZGC(-XX:+UseZGC)。
  • 选收集器本质是在吞吐量、停顿时间、内存占用三者之间取舍,没有绝对最优。
  • 评估指标:对比只看两点——GC 时间占总运行时间的比例与最坏停顿(P99),其余指标影响有限。
  • 迁移节奏:从 CMS 迁 G1 前先保留 GC 日志做前后对比,小流量灰度验证后再全量切换。

记忆点:并发收集器都在“并发标记/清理”阶段让用户线程继续跑,区别在于内存布局与是否搬移对象。

// 启动参数示例(注释即用法):
// java -Xms8g -Xmx8g -XX:+UseG1GC -XX:MaxGCPauseMillis=100 MyApp
// java -Xms100g -Xmx100g -XX:+UseZGC MyApp
public class CollectorDemo {
    public static void main(String[] args) {
        // 收集器由启动参数决定,业务代码通常无感知
        System.out.println("use: " + Runtime.version());
    }
}

常见追问 / 记忆点

  • 记忆点:CMS 已退场(碎片+浮动垃圾),G1 是默认(Region+可预测停顿),ZGC 面向超大堆(染色指针+读屏障)。
  • 追问:G1 靠 Remembered Set 跟踪跨 Region 引用,这是它能做到停顿可控的关键之一。
  • 追问:CMS 并发阶段与用户线程并行会产生“浮动垃圾”,预留空间不足会退化为 Serial Old,停顿反而更大。
  • 追问:G1 的 Mixed GC 优先回收垃圾最多的 Region,目标是“用最少的停顿清最多的垃圾”。
笔记加载中…