CMS 和 G1 垃圾回收器的区别是什么?

#Java#面试八股

CMS 和 G1 垃圾回收器的区别是什么?

结论先行:CMS 是老年代专用的并发标记-清除收集器,配合 ParNew 处理新生代,追求最短停顿但不压缩、有碎片;G1 是整堆管理的收集器,把堆切成大小相等的 Region,按「垃圾最多优先」回收,可设定停顿目标且自带整理。一句话:CMS 用碎片换停顿,G1 用可预测停顿换掉碎片问题,并因此成为 JDK 9 之后的默认收集器。

一、核心差异

维度CMSG1
管理范围只管老年代,新生代交给 ParNew整堆(新生代、老年代都是 Region 逻辑划分)
内存布局连续的 Eden / Survivor / Old等大 Region(1~32MB),逻辑分代,物理不连续
标记算法三色标记 + 增量更新(写后屏障)三色标记 + SATB(写前屏障)
压缩整理默认不压缩,靠 CMSFullGCsBeforeCompaction 定期整理回收即复制整理,天然无碎片
停顿控制无法设定目标,靠调阈值-XX:MaxGCPauseMillis 可设目标
大对象直接进老年代,易碎片化Humongous Region(≥ Region 一半)
适用堆4~8G4~32G(更大需 ZGC)
状态JDK 9 废弃,JDK 14 移除JDK 9+ 默认

二、流程对比

CMS(老年代):
  初始标记(STW) → 并发标记 → 重新标记(STW) → 并发清除 → 并发重置
  问题:清除不压缩 → 碎片 → 大对象分配失败 → concurrent mode failure → 单线程 Full GC

G1:
  Young GC(STW, 复制) ──→ 并发标记周期(初始标记借 Young GC / 并发标记 / 重新标记 / 清理)
        └─→ Mixed GC(多轮,回收 Young + 高垃圾占比 Old Region)
              └─→ 转移失败 → Full GC(单线程,兜底)

三、参数对照

# CMS:启动阈值 + 碎片治理 + 重新标记前先做一次 Young GC
java -XX:+UseConcMarkSweepGC -XX:+UseParNewGC \
     -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly \
     -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection \
     -XX:+CMSScavengeBeforeRemark -jar legacy.jar

# G1:停顿目标 + Region 大小 + 并发标记启动阈值
java -XX:+UseG1GC -XX:MaxGCPauseMillis=150 \
     -XX:G1HeapRegionSize=8m -XX:InitiatingHeapOccupancyPercent=45 \
     -XX:G1NewSizePercent=20 -XX:G1MaxNewSizePercent=40 \
     -XX:ConcGCThreads=4 -jar modern.jar

四、G1 如何在 Region 间排队

G1 不按「老年代/新生代」的顺序回收,而是按收益排队:

依据含义影响
垃圾占比Region 中可回收对象的比例占比越高越优先,这就是「Garbage First」的由来
GC 效率标记记在 Region 的标记位图里混合回收只挑标记过的候选集
预测模型用历史数据估算回收该 Region 的耗时保证总停顿不超过 MaxGCPauseMillis
记忆集成本跨 Region 引用越多,扫描越慢引用密集的 Region 会被降低优先级

回收顺序由「垃圾占比高 + 预测耗时短」共同决定,所以 G1 的停顿是「目标值 + 预测误差」,不是硬保证。

五、什么时候还该用 CMS

场景结论
JDK 8 且堆 < 4G、停顿敏感可用,但必须配碎片治理与阈值
堆 4~8G、对象分配速率平稳G1 更稳,CMS 的并发模式失败风险更高
大量大对象(如大数组、缓存块)避免 CMS,碎片会直接导致 Full GC
新项目不用 CMS,JDK 14 起已移除

六、常见追问

追问回答要点
为什么 CMS 被废弃碎片不可控、并发模式失败代价高、维护成本大,G1 在小中堆上已全面取代
G1 就一定没有长停顿吗有,转移失败与 Humongous 分配失败都会退化为 Full GC
为什么 G1 用 SATB 而不是增量更新SATB 只需在重新标记阶段处理删除的引用,且新对象直接视为存活,实现更简单、remark 更短
G1 的 Region 越大越好吗不是,Region 太大导致单次回收粒度粗、Humongous 阈值变高;一般 1~32MB,按堆大小自动推导
ZGC 与 G1 的关系ZGC 是并发转移,停顿 < 1ms 且与堆大小基本无关;G1 仍是分代复制,停顿随堆增长

小结

CMS 是「并发清除、不管碎片」的旧方案,G1 是「Region 化、可预测停顿、回收即整理」的新方案。答这一题的关键是讲清碎片与停顿控制这两条主线,而不是罗列参数。

笔记加载中…