写点什么

面试官:你能和我说一下 CMS 垃圾回收器吗?

作者:Java你猿哥
  • 2023-05-23
    湖南
  • 本文字数:1691 字

    阅读完需:约 6 分钟

面试官: 小伙子,CMS 垃圾收集器跟我讲讲?


候选人: CMS 全称 Concurrent Mark Sweep,是一种并发标记清除算法。它并发执行与用户程序,减少垃圾收集时程序暂停的时间。


面试官: 说白了,CMS 就是为了减少卡顿吧?


候选人: 是的,CMS 的核心目标就是达到并发收集、减少停顿。它的工作流程如下:

  1. 初始标记:只标记 GC Roots 能直接关联的对象,速度快,与用户线程共享运行,不需要 Stop The World。

// 初始标记代码示例private void initialMark() {    for (Object obj : strongRefs) {        CMSCollector.mark(obj);    }}
复制代码
  1. 并发标记:从 GC Roots 开始递归的标记对象图,与用户线程一起工作,需要部分 STW 阶段。

  2. 最终标记:修正在并发标记期间并发修改导致的错误标记,需要 STW。

  3. 并发清除:与用户线程一起工作,清除被标记的对象,不需要 STW。

  4. 并发重置:与用户线程一起工作,为下一次 GC 做准备,不需要 STW。


面试官: 说说并发标记和最终标记的区别?


候选人:

  • 并发标记阶段与用户线程一起运行,在标记过程中对象图可能被修改,会产生”脏标记“。需要最终标记修正。

  • 最终标记阶段需要 Stop The World,去修正并发标记期间的”脏标记“,确保正确的标记对象。

  • 如果没有最终标记阶段,并发标记的”脏标记“会导致非垃圾对象被清除,或者垃圾对象未被清除。

  • 所以,最终标记阶段是 CMS 算法关键,它通过 STW 去修正并发阶段的错误”脏标记“,使得 CMS 并发标记清除算法成为可能。


面试官: CMS 收集器的优缺点分别是什么?


候选人: CMS 收集器的主要优点是并发收集、低停顿,适用于对响应时间有要求的场景。 但是 CMS 也有一些缺点:

  1. 会产生大量空间碎片,空间利用率低。

  2. 标记和清除过程需要占用 CPU 资源,并发时会对程序性能产生一定影响。

  3. 并发执行时,需要处理一致性问题,会加大开发难度。

  4. 只适用于老年代回收,新生代仍需其他收集器配合。

  5. 浮动垃圾可能带来更长的 GC 停顿时间,不适用于需要极低停顿的场景。

所以,CMS 是一款比较经典的低停顿收集器,但也存在一定的缺陷, v 在 JDK9 后 G1 成为了更好的选择。但 CMS 算法本身的思想仍然值得我们学习。


面试官: 说说 CMS 收集器的“碎片化”问题?


候选人: CMS 是一种标记-清除算法,它会产生大量空间碎片,空间利用率低是一个缺点。这是因为:

  1. 在并发标记阶段,需与用户程序同时运行,无法移动对象。

  2. 在并发清除阶段,直接清除标记的垃圾对象,留下空隙。

  3. 这些空隙会产生空间碎片,并不连续,但空间可能不足以分配较大对象。

  4. 空间利用率降低,达不到理想状态,需要更频繁的 Major GC 来整理空间。 我们可以从 JVM 源码中看到 CMSCollector 在清除对象后直接造成碎片:

//CMSCollector.javaprivate void sweep phase() {    for (Object obj : markedObjects) {         freeMemory(obj); // 直接清除,产生碎片    }}
复制代码

为解决这个问题,CMS 做了一些努力:

  1. 采用 Free-list 维护小块空闲空间, satisfiy 小对象分配。

  2. 对象晋升到老年代时预留一定空间减少碎片。

  3. 空间报警触发 Minor GC 和 Full GC,做空间整合。

  4. 可配置启动 Incremental CMS 模式,进入并发清理阶段做连续空间整理。

但由于算法的限制,CMS 仍无法完全解决碎片空间问题,这也是它被 G1 等收集器替代的原因之一。


面试官: 谢谢详细的解释!CMS 收集器虽然有缺陷,但它的并发标记清除思想影响了后续的垃圾回收算法。


候选人: 是的,CMS 收集器提出了并发收集和低停顿的理念,其中的并发标记清除算法也为之后 G1 等收集器奠定了基础。它的关键思想值得我们学习:

  1. 将清理过程分为并发和 STW 两个阶段,大大减少停顿。

  2. 通过最终标记修正并发阶段的”脏标记“,使得并发标记成为可能。

  3. 采用 Free-list 和预留空间等手段减轻空间碎片问题。

  4. 根据空间利用率与 GC 时间的平衡,选择满足需求的收集频率。

这些思想为我们设计低停顿、高效的 GC 算法提供了参考,CMS 也因此成为 Java 垃圾收集史上的里程碑。所以,尽管它有缺陷,但它的算法思想和理念仍十分值得我们学习。


面试官: 很好,你对 CMS 收集器的理解已经相当透彻!希望你在日后继续深入学习其他垃圾收集算法。


候选人: 非常感谢您的夸奖和建议!我会继续努力学习和研究垃圾收集 theory 与实践,包括 G1、ZGC、Epsilon 等算法与案例。谢谢您的提问,让我有机会深入梳理 CMS 以及 Java 垃圾收集机制,收获颇丰!


面试官: 看来有点东西,你先等一下!

用户头像

Java你猿哥

关注

一只在编程路上渐行渐远的程序猿 2023-03-09 加入

关注我,了解更多Java、架构、Spring等知识

评论

发布
暂无评论
面试官:你能和我说一下 CMS 垃圾回收器吗?_Java_Java你猿哥_InfoQ写作社区