CMS(Concurrent Mark Sweep):是一种以牺牲吞吐量而获取最短回收停顿时间为目标的主要应用于服务端的收集器,基于标记-清除算法。
1.执行流程
如图我们可以发现主要有大概四个流程,分别是
初始标记
初始标记仅仅标记GC Roots可以直接关联到的对象,所以这段时间虽然STW(Stop The world),但是耗时是很短的。
并发标记
并发标记就是根据初始标记的基础上,向下追溯标记,这段时间是与应用线程并发执行的,所以用户在这个阶段是没有感觉到垃圾回收的。并发预清除
并发的标记在并发标记这个阶段,由新生代升级到老年代的对象,降低重新标记的工作量(减少STW时间)重新标记
暂停虚拟机,对于在并发标记阶段用户程序运行而产生的标记变动的那部分标记记录并发清理
并发的对需要清除的对象进行清理。- 重置进程
2.优点:
对老年代进行并发的,低停顿的收集。
3.缺点
CMS与CPU资源的权衡
在并发阶段,CMS虽然不会发生STW,但是会占用CPU资源,JVM的默认占用线程是(CPU数+3)/4,也就是说在4个CPU以上的计算机中,并发垃圾回收时,其占用的CPU资源是不低于25%的。如果是2个cpu,占用会达到50%。虚拟机提供过一种增量式的并发收集器,即与用户线程交替使用cpu资源,但是效果不佳。并发清除阶段的浮动垃圾问题
CMS在并发清除阶段,伴随着程序的运行,必然会产生许多的垃圾。而CMS并不是像其他收集器需要在老年代几乎完全被填满再收集。而是在达到一个阈值的时候进行收集,1.5为68%,1.6为92%。1.5时较为保守,没有什么大问题,但是1.6后只有8%作为用户程序运行空间。当用户空间不足时,就会产生Concurrent Mode Failure失败,这时候就会激发Serial old收集器重新进行老年代收集,这是一个单线程,停顿时间很长的收集器。所以会导致垃圾收集时间过长标记-清除空间碎片化问题
收集结束,由于算法原因会产生大量的碎片空间,当大对象请求空间不足时,会发生full GC。CMS提供了两个参数,第一个用于CMS顶不住时,进行一次碎片整理。第二个为执行多少次不压缩的full GC后,跟着来一次带压缩的。
4.重要参数
- -XX:CMSInitiatingOccupancyFraction:设置老年代触发CMS的比例‘
- -UseCMSCompactAtFullCollection:在CMS顶不住时,开启碎片整理,即对文件进行压缩
- -XX:CMSFullGCsBeforeCompaction :设置执行多少次不压缩的full GC后来一次带压缩的GC,默认为0(每次都压缩)