并发标记清除收集器组合 ParNew + CMS + Serial Old
开启选项:
-XX:+UseConcMarkSweepGC
并发标记清除(CMS)是以关注延迟为目标、十分优秀的垃圾回收算法,开启后,年轻代使用STW式的并行收集,老年代回收采用CMS进行垃圾回收,对延迟的关注也主要体现在老年代CMS上。
- 年轻代ParNew与并行收集器类似,而老年代CMS每个收集周期都要经历:初始标记、并发标记、重新标记、并发清除。
- 初始标记以STW的方式标记所有的根对象;(注意:仅仅标记所有的根对象)
- 并发标记则同应用线程一起并行,标记出根对象的可达路径;(结合第一步的根对象,开始遍历其可达路径)(这里的并行指的是不STW,应用线程运行他的,垃圾回收线程也同时运行,只不过我扫描我的根节点相应的可达路径,各自运行各自的,互相不影响)
- 在进行垃圾回收前,CMS再以一个STW进行重新标记,标记那些由mutator线程(指引起数据变化的线程,即应用线程)修改而可能错过的可达对象;(结合上一步订正的可达对象,不可达对象,作出订正标记)
- 最后得到的不可达对象将在并发清除阶段进行回收。值得注意的是,初始标记和重新标记都已优化为多线程执行(可能由于STW的原因,所以可以多线程执行)。CMS非常适合堆内存大、CPU核数多的服务器端应用,也是G1出现之前大型应用的首选收集器。
但是CMS并不完美,它有以下缺点:
- 由于并发进行,CMS在收集与应用线程会同时会增加对堆内存的占用,也就是说,CMS必须要在老年代堆内存用尽之前完成垃圾回收,否则CMS回收失败时,将触发担保机制,串行老年代收集器将会以STW的方式进行一次GC,从而造成较大停顿时间;
- 标记清除算法无法整理空间碎片,老年代空间会随着应用时长被逐步耗尽,最后将不得不通过担保机制对堆内存进行压缩。CMS也提供了参数-XX:CMSFullGCsBeForeCompaction(默认0,即每次都进行内存整理)来指定多少次CMS收集之后,进行一次压缩的Full GC。