CMS 收集器
CMS 收集器是一种最短回收时间为目标的收集器。在重视服务的相应速度,希望系统停顿时间最短,以给用户最好的体验
CMS 收集器,实现的算法是标记-清除算法,整个过程分为:
- 初始标记
- 并发标记
- 重新标记
- 并发清除
其中初始标记和重新标记需要 STW
实现过程
首先初始标记阶段找出 GC Root 所能直接关联的对象,速度很快,如 Java 栈中引用的对象、方法区中静态变量应用的对象和系统词典中应用的对象并标记,找出老年代对象在 eden 区有引用关系的对象并标记,最后把这些标记的对象复制到 to,在复制过程中还要判断活跃的对象 GC 年领是否已经达到了阈值,如果已经达到阈值,就直接晋升到老年代,YGC 结束之后将 from 和 to 的引用互换。其中大对象直接晋升到老年代,避免了在 eden 区、form、to 之间的复制。在发生 YGC 前,虚拟机会检查老年代最大的连续空间是否大于新生代所有对象的总空间,如果条件成立,那么进行 YGC 是安全的,如果不成立,检查虚拟机是允许担保失败,如果允许会检查老年代最大的连续空间是否大于历次晋升到老年代对象的平均大小或者新生代对象总大小,如果大于则进行 YGC ,如果条件不成立,或者虚拟机不允许空间担保失败,则进行一次 Full GC。
CMS 收集器缺点
- CMS 收集器对CPU 资源非常敏感
- CMS 收收集器无法处理浮动垃圾,可能出现 “ Concureent Mode Failure” 失败而导致另一次 Full GC 的产生。要是 CMS 在运行期间预留的内存无法满足程序需要,就会出现一次 “ Concureent Mode Failure” ,这个时候虚拟机临时启动 Serial Old 收集器重新来进行老年代的垃圾收集,这样停顿时间就很长了。
- 大量空间碎片,空间碎片过多的话会给分配大对象带来麻烦,即使老年代有很大的空间但是无法找到足够大的连续空间来分配当前对象,不得不提前触发一次 Full GC, 为了解决这个问题,CMS 提供了内存碎片整理的参数来设置,或者我进行几次不带碎片整理的 Full GC 之后,随后带一次碎片整理的 Full GC。