Bohr-L Bohr-L
首页
技术
常见面试题
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

刘博

I'm a slow walker, But I never walk backwards.
首页
技术
常见面试题
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 数据处理与存储类

  • Spring 生态类

  • 缓存问题类

  • 多线程类

  • JVM 类

    • JVM 中一次完整的 GC 流程(从 ygc 到 fgc)是怎样的
    • 如何判断对象可以被回收
    • 你知道哪些垃圾收集算法
    • 虚拟机为什么使用元空间替换了永久代
    • 简述 CMS 垃圾收集器的工作流程,它有什么优缺点?
      • 简述一下 JVM 的内存模型
      • 说说堆和栈的区别
      • 简述 Java 的对象结构
      • JVM 中的即时编译器(JIT)如何工作?
      • 什么是内存屏障?JVM 如何使用内存屏障保证指令执行顺序?
      • 如何排查和解决 JVM 内存泄漏问题?有哪些常用的工具和方法?
      • JVM 如何处理异常?try-catch-finally 结构在字节码层面是如何实现的?
    • MySQL 类

    • Java 8 + 特性类

    • 其他技术类

    • 常见面试题
    • JVM 类
    刘博
    2025-12-28
    目录

    简述 CMS 垃圾收集器的工作流程,它有什么优缺点?

    CMS(Concurrent Mark Sweep,并发标记 - 清除)是 JVM 中针对老年代的垃圾收集器,核心目标是 “减少 STW(Stop The World)时间”,适用于高并发、对响应时间敏感的应用(如电商网站、金融交易系统),工作流程和优缺点如下:

    # 1. CMS 垃圾收集器的工作流程

    CMS 基于 “标记 - 清除” 算法,将 GC 过程分为 4 个步骤,其中 2 个步骤与用户线程并发执行,仅 2 个步骤需要 STW,大幅缩短 STW 时间:

    # (1)初始标记(Initial Mark,STW)
    • 目标:标记 GC Roots 直接引用的老年代对象(如线程栈引用、静态变量引用的老年代对象);
    • 过程:暂停所有用户线程(STW),快速遍历 GC Roots,标记直接引用的老年代对象;
    • 特点:STW 时间极短(通常毫秒级),因为仅标记 “直接引用”,不遍历引用链。
    # (2)并发标记(Concurrent Mark,非 STW)
    • 目标:从初始标记的对象出发,遍历老年代的所有对象引用链,标记所有存活对象;
    • 过程:恢复用户线程,GC 线程与用户线程并发执行,遍历老年代的对象引用,标记存活对象;
    • 特点:无 STW,不影响用户线程响应性,但会占用 CPU 资源(默认 GC 线程数为(CPU核心数 + 3) / 4),可能导致应用吞吐量下降。
    # (3)重新标记(Remark,STW)
    • 目标:修正并发标记期间因用户线程操作导致的 “标记变动”(即 “浮动垃圾” 的反向问题);
    • 背景:并发标记时,用户线程可能修改对象引用(如删除引用、新增引用),导致部分对象的标记状态不准确(如并发标记时标记为存活,但用户线程后续断开引用,变为死亡对象;或并发标记时未标记,但用户线程新增引用,变为存活对象);
    • 过程:再次暂停所有用户线程(STW),通过 “Card Table”(记录老年代对象引用变动的表)快速找到变动的对象,修正标记状态;
    • 特点:STW 时间比初始标记长(通常几十毫秒),但远短于 Serial Old 收集器的 STW 时间;JDK 6 后引入 “增量重新标记”(Incremental Remark),进一步缩短 STW 时间。
    # (4)并发清除(Concurrent Sweep,非 STW)
    • 目标:清除老年代中未被标记的死亡对象,释放内存;
    • 过程:恢复用户线程,GC 线程与用户线程并发执行,遍历老年代,清除未标记的对象;
    • 特点:无 STW,不影响用户线程,但会产生内存碎片(标记 - 清除算法的固有问题);同时,并发清除期间用户线程产生的新死亡对象(“浮动垃圾”)无法被本次 GC 回收,需等待下次 GC。

    # 2. CMS 垃圾收集器的优点

    • 1. 低 STW 时间:仅初始标记和重新标记需要 STW,总 STW 时间通常在 10-100 毫秒,远低于 Serial Old(秒级)和 Parallel Old(百毫秒 - 秒级)收集器,适合对响应时间敏感的应用;
    • 2. 并发执行:并发标记和并发清除与用户线程并发执行,用户线程无需长时间等待,应用响应性好;
    • 3. 吞吐量较高:虽然并发执行会占用 CPU 资源,但相比 Serial Old(单线程 GC),CMS 的 GC 效率更高,应用吞吐量(单位时间处理请求数)损失较小;
    • 4. 适配老年代特性:老年代对象存活时间长,死亡对象少,标记 - 清除算法的 “标记成本低”,适合 CMS 的并发标记流程。

    # 3. CMS 垃圾收集器的缺点

    • 1. 产生内存碎片:基于标记 - 清除算法,并发清除后老年代会产生大量不连续的空闲内存块;当需要分配大对象时,可能因找不到足够大的连续空闲块而触发 “Full GC 降级”(即用 Serial Old 收集器进行标记 - 整理,STW 时间长);
    • 2. 产生浮动垃圾:并发清除期间,用户线程产生的新死亡对象无法被本次 GC 回收,称为 “浮动垃圾”;若浮动垃圾过多,可能导致老年代空间提前满,触发下一次 GC(甚至 FGC 降级);
    • 3. CPU 资源敏感:并发标记和并发清除需要 GC 线程与用户线程抢占 CPU 资源,当 CPU 核心数较少(如 2 核)时,GC 线程会占用较多 CPU(默认(2+3)/4=1个核心),导致应用吞吐量下降;
    • 4. 无法处理大堆内存:当老年代内存过大(如超过 8GB)时,并发标记和重新标记的时间会显著增加,STW 时间无法控制,此时推荐使用 G1 收集器;
    • 5. 老年代 GC 触发时机难把握:CMS 默认在老年代内存使用率达到-XX:CMSInitiatingOccupancyFraction(默认 92%)时触发 GC;若触发过晚,可能因老年代空间不足导致 FGC 降级;若触发过早,会增加 GC 频率,浪费 CPU 资源。

    # 4. CMS 的适用场景与替代方案

    • 适用场景:堆内存中等(老年代 < 8GB)、对响应时间敏感、CPU 核心数充足(4 核及以上)的应用(如电商订单系统、支付系统);
    • 替代方案:JDK 9 后 CMS 被标记为 deprecated(过时),推荐用G1 收集器替代;G1 支持分区收集,兼顾低 STW 时间和无内存碎片,适配大堆内存(如 10GB-100GB)。

    上次更新: 12/30/2025
    虚拟机为什么使用元空间替换了永久代
    简述一下 JVM 的内存模型

    ← 虚拟机为什么使用元空间替换了永久代 简述一下 JVM 的内存模型→

    最近更新
    01
    CPU 使用率较高排查和解决
    12-29
    02
    JVM OOM 问题如何排查和解决
    12-29
    03
    接口防刷怎么实现?
    12-29
    更多文章>
    Theme by Vdoing | Copyright © 2025-2026 Bohr-L's note
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式