CMS入门理解
什么是CMS?
CMS 是 Concurrent Mark Sweep 的缩写,直译过来就是并发的标记清除算法。
CMS是搭配新生代的串行和并行的垃圾回收器使用,不能和新生代的Parallel Scavenge配合使用。
CMS针对老年代,采用标记-清除算法,用户线程和垃圾回收线程并行执行,特点是低暂停
注意:STW(stop the world):可以理解为暂停用户线程
流程
CMS整个垃圾收集过程更长了(但是不重要),但是STW的时间变短了,而且在垃圾收集过程中大部分的时间用户线程也还在执行,所以用户体验更好了,但是吞吐量更低了(单位时间内执行的用户线程更少了)
初始标记:
- STW,暂停所有工作线程
- 然后标记出GC Roots能直达的对象(并不需要找到所有可达对象,所以用时很快)
- 一旦标记完,就恢复线程继续执行
- 这个阶段比较短
并发标记:
- 从上一个阶段标记出的对象,开始遍历整个老年代,标记出所有可达对象
- 耗时会比较长
- 但是不需要STW,用户线程和垃圾收集线程一起执行
- 三色标记
这个阶段可能有些问题,用户线程在工作,本来有些对象是可达的,但变成了垃圾对象,有些对象是垃圾对象,但是某些原因又变成了非垃圾对象(比如final)。这些问题垃圾收集器都会帮我们解决,就不深究了
重新标记:
- 上一个阶段标记的对象,可能会有误差,需要进行修正
- 需要STW,但是时间也不会很长
- 增量更新
并发清理:
- 删除垃圾对象
- 由于不需要移动对象,这个阶段也可以和用户线程一起执行,不需要执行STW
并发重置:
- 等待下次CMS的触发
- 与用户线程同时执行
CMS问题总结
- 如果在并发标记、并发清理过程中,由于用户线程同时在执行,如果有新对象要进入老年代,但是空间又不够,就会导致 " concurrent mode failure ",此时就会利用Serial Old(暂停所有的用户线程,全部进行垃圾回收,所有垃圾对象回收后,才让用户线程工作)来做一次垃圾收集,就会做一次全局的STW
- 在并发清理过程中,可能产生新的垃圾,这些就是“浮动垃圾”,只能等到下一次GC时来处理
- 由于采用的是标记-清除算法,所以会产生内部碎片,可以通过参数-XX:+UseCMSCompactAtFullCollection可以让JVM在执行完标记-清除算法后再做一次整理,也可以通过 -XX:CMSFullGCsBeforeCompaction来指定多少次GC后来做整理,默认是0,表示多少次GC后都整理