CMS垃圾收集器总结

目录

一.执行步骤

二.优点和缺点

三.关键点和重要参数


一.执行步骤

1.初始标记(stw):只标记从gc root直接引用的对象。

2.并发标记:从初始标记的对象出发,继续标记。如果标记期间有发生晋升、老年代直接分配、引用关系变更等,会记录dirty card。

3.并发预清理:标记在上一阶段新生代新分配的对象到老年代的引用;遍历dirty card,根据dirty card的当前引用关系,重新标记,目的是减轻最终标记stw时间。

4.可中断的并发预清理:不断重复预清理的过程,直到时间到达CMSMaxAbortablePrecleanTime(默认5s)设置的阀值,或是迎来一次young gc。

5.最终标记(stw):遍历gc root ,重新标记(此处我的理解是遇到之前标记过的就停止);遍历dirty card,重新标记。

6.并发清理:清理上一阶段未被标记的对象。

7.并发重置:清理本次cms gc的上下文信息,为下一次gc做准备。

二.优点和缺点

优点:并发收集,降低stw时间。

缺点:1.并发时占用cpu 。

           2.无法处理浮动垃圾(已被标记对象转换成的垃圾)。

           3.cms基于标记清除算法,会产生空间碎片。

三.关键点和重要参数

1.在最终标记时会遍历young区所有对象,如果此时young区对象较多,会耗时较长,有两种解决办法。

第一个,是等待在可中断的并发预清理阶段执行一次young gc,CMSScheduleRemarkEdenSizeThreshold(默认2M)、CMSScheduleRemarkEdenPenetration(默认50%),CMSMaxAbortablePrecleanTime(默认5s),CMSMaxAbortablePrecleanLoops(默认0),通过这几个参数来控制该阶段是否执行与执行的计划(不过我自己做了实验CMSScheduleRemarkEdenPenetration这个参数并没有起到应有的效果,此处有些困惑)。

第二个,可以利用cms提供的-XX:+CMSScavengeBeforeRemark参数来控制在最终标记前执行一次young gc(并不会绝对执行,jvm会做一定判断)。

2.产生较多的空间碎片

空间碎片过多可能引发promotion failed (空间担保失败、晋升失败)和 concurrent mode failure 异常,此时cms gc会降级成full gc,这里的full gc是使用标记清除算法。可通过-XX:UseCMSCompactAtFullCollection,-XX:CMSFullGCBeforeCompaction 来设置是否开启full gc的整理阶段以及几次full gc后进行一次整理(默认开启,每次都进行整理)。

还可以通过减小cms gc阀值和增大老年代空间来降低碎片产生的影响。

3.触发cms gc的时机

通过-XX:+UseCMSInitiatingOccupancyOnly 和  -XX:CMSInitiatingOccupancyFraction 来控制,如果不设置这两个参数,jvm会自行判断cms gc何时执行,这种情况下出现问题不好排查。

你可能感兴趣的:(jvm)