CMS收集器
CMS收集器是以最短停顿时间为目标的收集器,就是注重响应时间优先。基于标记清楚算法实现,整个回收过程分为以下四步:
- 初始标记
- 并发标记
- 重新标记
- 并发清除
初始标记:该阶段会标记所有和Gc Roots节点直接相连的对象,该阶段需要暂停用户线程,即Stop the world。
并发标记:从GC Roots的直接关联对象开始遍历整个对象图的过程,这个过程耗时相对比较长,但是不需要停顿用户线程。
重新标记:标记因用户线程并发运行而导致标记产生变动的那一部分对象,该阶段也会暂停用户线程,但是时间比较短。
并发清除:清理删除掉标记阶段被判断为死亡的对象,由于是基于标记清除算法的,所以不需要移动存活对象,因此不需要暂停用户线程,所以该阶段也是并发运行的。
总结下来:只有初始标记和重新标记两个阶段需要停顿用户线程。
运行示意图如下:
CMS收集器的缺点:
- 对处理器资源比较敏感,并发阶段虽然不会导致用户线程停顿,但是却需要占用一部分处理器资源从而导致应用整体的吞吐量下降。CMS默认启动的回收线程数为(处理器核心数量 + 3)/ 4。
- 由于CMS收集器无法处理浮动垃圾,有可能失败导致一次完全的Stop the world的Full GC产生。在CMS的并发标记和并发清除阶段,用户线程是还在继续运行的,程序在运行自然就还会伴随有新的垃圾对象产生,但是这一部分垃圾对象是出现在标记过程结束以后,CMS无法在当次收集中处理掉他们,只能把它们留到下一次垃圾收集时才能回收掉,这一部分就是浮动垃圾。所以CMS收集器不能等到老年代完全满才会触发,需要达到一个阈值就会触发,JDK6为92%,也就是对象占比达到这个值就会触发回收。
- 最后一个就是,由于它是基于标记清除算法来实现的,所有会产生大量的内存碎片。由于存在内存碎片,虽然老年代中还有足够的空间,但是无法分配连续的大对象,而导致Full GC。