# CMS (Concurrent Mark Sweep 并发标记清理)

CMS设计的目标就是获取最低停顿时间(stop the world停顿时间),它是基于标记-清除算法实现的。

# CMS 收集器的工作流程

  1. 初始标记:只标记和GC Roots能直连的对象,速度快,会发生(stop the world)
  2. 并发标记:和应用线程并发执行,遍历初始标记阶段标记过的对象,标记这些对象的可达对象。
  3. 重新标记:由于并发标记是和应用线程是并发执行的,所以有些标记过的对象发生了变化。这个过程比初始标记用时长,但是比并发标记阶段用时短。会发生(stop the world)
  4. 并发清除:和应用线程一起运行。基于标记对象,直接清理对象。

# CMS 的缺点

  1. 垃圾碎片问题
    • 原因:由于CMS采用的是标记-清除算法,所以不可避免会有内存碎片问题。
    • 解决:使用-XX:+CMSFullGCsBeforeCompaction=n,意思是在上次CMS并发GC执行过后,到底还要做多少Full GC才做压缩。默认是0,也就是说每次CMS GC顶不住了转入Full GC时都要压缩。
  2. 对 CPU 资源敏感
    • CMS 默认启动的回收线程数是(CPU数量+3)/4,当CPU不足4个时,CMS 对用户程序的影响可能变大
  3. 无法处理浮动垃圾
    • 由于CMS 并发清除阶段用户线程还在运行着,伴随程序运行自然就回产生新的垃圾,这一部分垃圾(浮动垃圾)没有被标记,CMS 无法在当次收集中处理它们,只好留待下一次GC时在清理掉。
    • 可能出现 “Concurrent Mode Failure” 失败而导致另一次Full GC 的产生。

# 为什么配置了CMS GC,却触发了Full GC

  1. 大对象分配时,年轻代放不下,直接去老年代,结果老年代也放不下,(内存碎片问题:使用 标记-清除 算法的缺点)。
  2. CMS GC失败,无法处理浮动垃圾,可能出现(Concurrent Mode Failure)失败而导致。
  3. jmap -histo 人为执行了命令。

# CMS GC日志分析 👍

![CMS GC日志分析](/img/java/CMS GC日志分析.png)

Last Updated: 21 days ago