CMS垃圾回收器的原理
CMS全称Concurrent Mark Sweep(并发标记清除),它在年轻代使用复制算法,老年代使用标记-清除算法。
CMS设计的目标是,避免老年代GC时出现长时间的卡顿。而实现该目标的原理就是,将垃圾回收过程中耗时的操作,做成了和用户线程并行。这也是为什么cms被称为并发标记清除,并且能够减少停顿的原因。
由于老年代使用的是标记-清楚算法,所以缺点也很明显,就是内存碎片问题。
CMS回收的过程
1.初始标记
初始标记阶段,就是简单地标记下GC root对象,不用向下追溯,因为追溯的tracing阶段是非常耗时的。
初始标记阶段是会导致STW的,但是由于只标记GC root对象,所以速度很快。
2.并发标记
并发标记阶段,就是进行tracing,标记所有可达对象,该过程是和用户线程一起并行进行的。
由于标记追溯过程中,没有STW并且和用户线程并行。所以,对象也是时刻处在变化过程中的,所以后续会有一个重新标记的过程。
3.并发预清理
并发预清理,就是进行重新标记,
4.最终标记
最终标记,会触发STW。
5.并发清除
并发清除,此时用户线程被激活,并且垃圾回收线程和用户线程并行。由于垃圾回收过程中,用户线程也会不断地产生新的垃圾,当前事务GC线程是无法回收这些新产生的垃圾,这些新产生的垃圾被称为“浮动垃圾”。
6.并发重置
此阶段与用户线程并发执行,重置 CMS内部数据,为下一次GC做准备。
预留空间
CMS回收过程中,用户线程也会不停产生新的垃圾,因此需要保证有充足的空间预留给用户使用。如果等到老年代满了,再开启GC,会导致CMS临时使用Serial Old进行回收,那么将会大大增加STW的时间。
因此,可以通过设置-XX:CMSInitiatingOccupancyFraction来控制,一般预留设置30%,也就是当老年代的空间使用率达到70%时,触发GC回收。
优缺点
优点:
较少的卡顿。
缺点:
内存碎片问题
占用更多CPU资源
预留空间导致空间浪费