侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

CMS垃圾收集器的工作流程及Concurrent Mode Failure分析

2025-12-6 / 0 评论 / 4 阅读

题目

CMS垃圾收集器的工作流程及Concurrent Mode Failure分析

信息

  • 类型:问答
  • 难度:⭐⭐

考点

垃圾收集器原理,内存回收机制,GC调优

快速回答

CMS(Concurrent Mark Sweep)收集器工作流程:

  1. 初始标记(STW):标记GC Roots直接关联对象
  2. 并发标记:与用户线程并行标记可达对象
  3. 重新标记(STW):修正并发标记期间的变动
  4. 并发清除:与用户线程并行清理垃圾

Concurrent Mode Failure触发条件:老年代空间不足时发生,导致Full GC。避免方法:

  • 增大老年代空间(-XX:NewRatio)
  • 降低触发阈值(-XX:CMSInitiatingOccupancyFraction)
  • 启用内存碎片整理(-XX:+UseCMSCompactAtFullCollection)
## 解析

一、CMS工作流程详解

CMS是针对老年代的并发收集器,通过减少STW时间提升响应速度:

  1. 初始标记(Initial Mark - STW)
    暂停所有应用线程,标记GC Roots直接关联的对象(速度极快)
  2. 并发标记(Concurrent Mark)
    与应用线程并发执行,遍历对象图标记存活对象(耗时最长)
  3. 重新标记(Remark - STW)
    修正并发标记期间因用户线程运行导致的标记变动(使用增量更新算法)
  4. 并发清除(Concurrent Sweep)
    与应用线程并发执行,清理未标记的垃圾对象

二、Concurrent Mode Failure原理

当出现以下情况时触发:
在并发清理阶段,老年代空间不足以容纳新晋升的对象。此时JVM会中止CMS并发周期,立即触发Serial Old收集器进行Full GC(长时间STW)。

根本原因
1. 老年代空间分配过小
2. 对象晋升速度过快
3. 内存碎片导致无法分配连续空间

三、避免策略与最佳实践

1. 参数调优

// 推荐配置示例
-XX:+UseConcMarkSweepGC 
-XX:CMSInitiatingOccupancyFraction=70  // 老年代70%时启动CMS
-XX:+UseCMSInitiatingOccupancyOnly     // 强制使用设定阈值
-XX:+UseCMSCompactAtFullCollection    // FullGC时压缩内存
-XX:CMSFullGCsBeforeCompaction=5      // 每5次FullGC压缩一次
-XX:NewRatio=3                        // 老年代/新生代=3:1

2. 监控与诊断

  • 通过GC日志检测:
    -Xlog:gc*:file=gc.log
  • 关键日志标识:
    [Concurrent Mode Failure]
  • 使用工具分析:JVisualVM, GCViewer

3. 替代方案

当频繁出现Concurrent Mode Failure时,考虑:
- 升级到G1收集器:
-XX:+UseG1GC
- 切换到ZGC(JDK11+):
-XX:+UseZGC

四、常见错误

  • 错误1:未设置-XX:+UseCMSInitiatingOccupancyOnly导致JVM自动调整阈值
  • 错误2:过度降低CMS触发阈值导致频繁GC
  • 错误3:未启用内存压缩导致碎片化加剧

五、扩展知识

  • CMS vs G1:G1通过Region分区和预测模型避免内存碎片问题
  • 晋升担保失败:当Survivor空间不足时,对象会直接进入老年代,可能加剧Concurrent Mode Failure
  • JDK版本影响:JDK8中CMS仍可用,JDK14后已被移除