CMS 优缺点与碎片问题
候选人小赵在面试蚂蚁 P7 时,面试官问道:
"CMS 和 G1 相比,有什么缺点?"
小赵说:"CMS 会产生内存碎片..."面试官追问:"碎片问题具体会导致什么问题?"
小赵答不上来。面试官继续追问:"为什么 JDK 14 把 CMS 废弃了?"
小赵彻底卡住了...
一、核心问题:CMS 优缺点 🔴
1.1 问题拆解
1.2 ❌ 错误示范
候选人原话 A:"CMS 比 G1 更快,所以应该用 CMS。"
问题诊断:CMS 的并发阶段消耗 CPU,降低应用吞吐量。在高并发场景下,CMS 的吞吐量通常低于 G1。
候选人原话 B:"G1 完美解决了 CMS 的所有问题。"
问题诊断:G1 解决了碎片问题,但引入了新的问题——Remembered Set 的内存开销、YGC 停顿等。
1.3 标准回答
P5 级别:CMS 的优势
CMS 的核心优势:并发标记
CMS 的最大特点是并发标记和并发清除,在大部分阶段与用户线程并发运行,减少了 Stop-The-World 的时间:
适用场景:
- 对停顿时间有要求的交互式应用
- 老年代对象相对稳定的场景
P6 级别:CMS 的三大问题
问题 1:内存碎片
CMS 使用标记-清除算法,产生大量内存碎片:
碎片化的后果:
- 大对象分配失败
- 触发 Serial Old 的 Full GC(最长的停顿)
问题 2:浮动垃圾
并发标记期间产生的"浮动垃圾"需要等待下一次 GC 才能回收:
问题 3:Concurrent Mode Failure
如果在并发清除期间老年代满了,无法容纳新分配对象 + 浮动垃圾:
触发 Serial Old Full GC,停顿时间可能达到 10 秒以上。
P7 级别:G1 的解决思路
G1 如何解决碎片问题:
G1 使用标记-整理算法(而非标记-清除):
G1 的整理是并发的,不会产生长时间的 STW。
G1 的停顿时间控制:
G1 支持设置停顿时间目标:
G1 通过Mixed GC(混合 GC)来满足停顿时间目标——在一次停顿中只回收部分 Region。
【面试官心理】 这道题我能问到 P7 级别,是因为 CMS vs G1 的对比涉及了 GC 演进的工程权衡。能说清碎片问题导致 Serial Old Full GC 的候选人说明他有过生产调优经验。
1.4 追问升级
追问:JDK 14 废弃 CMS 时,推荐用什么替代?
- JDK 8 及之前:ParNew + CMS → G1
- JDK 11+:G1(默认)、ZGC(超低停顿)
二、生产调优 🟡
2.1 CMS 参数调优
2.2 G1 的配置
面试加分点:能说出"JDK 11 的 ZGC 通过着色指针和读屏障,实现了停顿时间 < 1ms 的目标,且停顿时间不随堆大小增加而增加(停顿时间和存活对象数量无关,只和 Roots 数量有关)",说明他关注了 ZGC 的技术突破。
面试陷阱:被问到"CMS 产生碎片后,能通过配置解决吗",很多人会说"可以"。准确答案是:只能缓解,不能根本解决。-XX:CMSFullGCsBeforeCompaction 可以定期整理,但整理本身需要 Full GC。根本解决方案是迁移到 G1。