别再背八股了!面试说清 CMS 回收器,就靠这篇了

“面试官问我 CMS 是什么,我脑子一热,差点说成了‘内容管理系统’!”这是我一个做了5年 Java 的朋友最近社招面试的真实经历。从这件事我意识到,CMS(Concurrent Mark Sweep)垃圾回收器,虽然老牌,但在很多面试中依然是重点。所以今天,小米就来讲讲我是怎么“跟 CMS 打交道”的——希望能帮到即将跳槽、社招面试的你。

故事的起点:我和 CMS 的第一次“相遇”

还记得那年我第一次维护一个线上老项目,Tomcat 启动参数里赫然写着:

-XX:+UseConcMarkSweepGC

当时的我一脸懵:“这啥?新玩意儿?”

我去查资料才知道,原来它就是传说中的“低延迟垃圾回收器”——CMS,老年代的明星选手,曾一度是互联网公司争相使用的主流 GC 方案。

而这次,也让我开始正式接触 JVM 内存管理的世界。

CMS 的目标是什么?

CMS,全称是 Concurrent Mark Sweep,中文叫“并发标记-清除”。顾名思义,它的最大特点就是——尽量减少 STW(Stop The World)时间,也就是让垃圾回收这件事尽量不打扰业务线程运行

它的“信仰”是:用户体验优先,延迟比吞吐更重要。

也正因为如此,它被广泛用于对响应时间有要求的 Web 服务类系统,像电商、支付、在线教育等系统中。

CMS 的工作流程(记住这四个阶段)

在我看来,CMS 就像是个不打扰别人的清洁工,它一边让用户用着房间,一边偷偷打扫:

1、初始标记(Initial Mark)

  • 短暂停顿(STW)
  • 标记所有 GC Root 直接关联的对象
  • 非常快,一般几毫秒内完成

2、并发标记(Concurrent Mark)

  • 和应用线程同时进行
  • 遍历整个对象图,找出存活对象

3、重新标记(Remark)

  • 再次暂停(STW)
  • 解决并发标记期间产生的对象变动(比如新引用)
  • 相对耗时,是整个过程的瓶颈之一

4、并发清除(Concurrent Sweep)

  • 清理垃圾对象,回收空间
  • 同样是和用户线程一起进行的

总结一句话:只有初始标记和重新标记两个步骤会暂停应用,其它阶段是“边跑边收”。

我踩过的几个 CMS“大坑”

作为一个在生产环境中维护过 CMS 回收器的人,小米必须给你讲几个“实战坑点”。

  1. 碎片化严重

CMS 是“标记-清除”算法,所以不会像 G1 或 Parallel Old 那样做“压缩”。清理之后留下的是“一个个小碎片”。

这意味着:大对象分配容易失败,即使总内存够,但没有一块连续空间就 GG。

解决方案:加上 -XX:+UseCMSCompactAtFullCollection 参数(默认就是 true),并设定压缩频率 -XX:CMSFullGCsBeforeCompaction=5,让 CMS 每执行几次 Full GC 就顺带整理一次空间。

  1. 并发失败(Concurrent Mode Failure)

这个问题听上去就让人心慌:回收器还没干完活,堆就满了!

这通常发生在 CMS 清理速度赶不上对象增长速度时,JVM 被迫切换为“Stop The World 的 Serial Old”模式,系统就顿了,甚至会出现卡顿报警。

应对方法:

  • 增加老年代大小 -XX:CMSInitiatingOccupancyFraction=75(默认是92)
  • 启用 -XX:+UseCMSInitiatingOccupancyOnly 控制 GC 触发时机
  1. 浮动垃圾(Floating Garbage)

由于 CMS 在并发标记、清理期间,业务线程还在创建新对象,所以这些“新生代对象”在 GC 时根本就没看见。

这些没清理到的对象就叫:浮动垃圾

这就是为什么 CMS 没法做到“完全回收”,它需要依靠多次回收才能慢慢清理干净。

看新机会的可看看

民族企业核心部门,前、后端or测试>>>机会 待遇还可以,感兴趣试试~

再聊聊 CMS 的参数优化

你面试的时候,光说机制还不够,能讲讲调优,就显得你“干过活”。

常见调优参数:

经验值建议:

  • 新生代大小设大一点,避免频繁 Minor GC
  • 老年代使用率到 70~75% 左右就开始 GC
  • 定期触发 Full GC,压碎片(适度使用)

CMS 的退场:被谁取代了?

2017 年 Oracle 宣布:CMS 将在 JDK 9 后被标记为“deprecated”

它的接班人是谁?那就是 G1(Garbage First)

为什么?因为:

  • G1 支持压缩(解决了碎片问题)
  • G1 更智能(自动按 Region 分区)
  • G1 有更短更可控的暂停时间

不过,如果你面试中提到:“虽然 CMS 被 G1 替代,但它依然在很多线上系统中运行,了解它是必要的。”——你绝对是加分项!

面试怎么说 CMS?

来,小米总结一段“答题模板”送你:

CMS 是一种以降低 GC 停顿时间为目标的垃圾回收器,采用标记-清除算法,在初始标记和重新标记阶段会暂停业务线程,其余阶段与业务线程并发执行。适用于对响应时间要求高的场景。缺点是内存碎片化严重、容易出现并发失败。调优时可以设置 CMSInitiatingOccupancyFraction 来提前触发 GC,并定期做 Full GC 以压缩空间。目前 CMS 在 JDK 9 后已被标记为废弃,G1 是其继任者。

简洁、有层次、还带优化经验,一听就是干过的!

建议

如果你还在用 CMS,那一定要:

  • 监控老年代使用率
  • 留意 GC 日志是否出现 Concurrent Mode Failure
  • 考虑是否能升级 G1 或 ZGC(JDK11+)

而如果你准备社招,别光死背概念,要结合故事、项目、场景去说,才能让面试官感受到你的“实战经验”。

END

CMS 是一段经典的 JVM 回忆,也是 Java 调优道路上的“必经之坑”。虽然它已经慢慢退场,但它的机制和思维,依然影响着后来的垃圾回收器设计。

面试,是回顾和总结的好机会。希望今天的这篇文章,能帮你更自信地面对面试中的 JVM 回收问题,也希望你不再被 CMS 的“初始标记”和“重新标记”绕晕啦。

如果你觉得这篇文章有帮助,欢迎点赞、转发给正在找工作的朋友,也欢迎留言说说你被 CMS“坑”过的经历,我们一起成长!

——转载自:软件求生

全部评论

相关推荐

点赞 评论 收藏
分享
评论
4
10
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务