# CMS (Concurrent Mark Sweep 并发标记清理)
CMS
设计的目标就是获取最低停顿时间(stop the world停顿时间),它是基于标记-清除算法实现的。
# CMS 收集器的工作流程
- 初始标记:只标记和GC Roots能直连的对象,速度快,会发生(stop the world)
- 并发标记:和应用线程并发执行,遍历初始标记阶段标记过的对象,标记这些对象的可达对象。
- 重新标记:由于并发标记是和应用线程是并发执行的,所以有些标记过的对象发生了变化。这个过程比初始标记用时长,但是比并发标记阶段用时短。会发生(stop the world)
- 并发清除:和应用线程一起运行。基于标记对象,直接清理对象。
# CMS 的缺点
- 垃圾碎片问题
- 原因:由于CMS采用的是标记-清除算法,所以不可避免会有内存碎片问题。
- 解决:使用-XX:+CMSFullGCsBeforeCompaction=n,意思是在上次CMS并发GC执行过后,到底还要做多少Full GC才做压缩。默认是0,也就是说每次CMS GC顶不住了转入Full GC时都要压缩。
- 对 CPU 资源敏感
- CMS 默认启动的回收线程数是(CPU数量+3)/4,当CPU不足4个时,CMS 对用户程序的影响可能变大
- 无法处理浮动垃圾
- 由于CMS 并发清除阶段用户线程还在运行着,伴随程序运行自然就回产生新的垃圾,这一部分垃圾(浮动垃圾)没有被标记,CMS 无法在当次收集中处理它们,只好留待下一次GC时在清理掉。
- 可能出现 “Concurrent Mode Failure” 失败而导致另一次Full GC 的产生。
# 为什么配置了CMS GC,却触发了Full GC
- 大对象分配时,年轻代放不下,直接去老年代,结果老年代也放不下,(内存碎片问题:使用 标记-清除 算法的缺点)。
- CMS GC失败,无法处理浮动垃圾,可能出现(Concurrent Mode Failure)失败而导致。
- jmap -histo 人为执行了命令。
# CMS GC日志分析 👍
![CMS GC日志分析](/img/java/CMS GC日志分析.png)