别再背八股了!面试说清 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 没法做到"完全回收",它需要依靠多次回收才能慢慢清理干净。

再聊聊 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"坑"过的经历,我们一起成长!

我是小米,一个喜欢分享技术的31岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号"软件求生",获取更多技术干货!

相关推荐
驭渊的小故事11 分钟前
Spring AI Alibaba 实战:从maven依赖治理到声明式工具调用
java·人工智能·spring
Elastic 中国社区官方博客35 分钟前
我们如何通过 70 多个拉取请求,将 OpenTelemetry Java agent 迁移到 invokedynamic
java·大数据·开发语言·elasticsearch·搜索引擎·全文检索·es
tyn1881 小时前
记录本地安装nacos服务的方法及异常
java·开发语言
步行cgn1 小时前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
y1su2 小时前
Leetcode 字符串模板
java·数据结构·算法·leetcode·职场和发展·动态规划
码事漫谈2 小时前
AI 读你的提示词,其实很没耐心
后端
用户8356290780513 小时前
如何使用 Python 格式化 Excel 单元格中的长文本
后端·python
我命由我123453 小时前
Python 开发 - Python 的 pathlib
java·开发语言·后端·python·学习·java-ee·学习方法
IT_陈寒3 小时前
Java性能优化完全指南
前端·人工智能·后端
电子IT笔记3 小时前
对接群晖NAS,上传和删除踩坑记录
前端·后端