【JVM】落日黄昏后:CMS垃圾回收器

CMS(Concurrent Mark Sweep)应用场景

CMS是一种以获取最短回收停顿时间为目标的收集器。目前很大一部分的Java应用集中在互联网网站或者基于浏览器的B/S系统的服务端上,这类应用一般都会较为关注服务的响应速度,但愿系统停顿时间尽量短,以给用户带来良好的交互体验。CMS收集器就很是符合这类应用的需求。算法

CMS的运做过程

图片
CMS收集器是基于标记-清除算法实现的,整个过程分为四个步骤,包括:浏览器

  • 初始标记(initial mark)
    这个阶段是STW的,但仅仅只是标记一下GCRoots能直接关联到的对象,因此速度很快并发

  • 并发标记(concurrent mark)
    并发标记阶段就是从GC Roots的直接关联对象开始遍历整个对象图的过程,这个过程耗时较长可是不须要停顿用户线程,能够与垃圾收集线程一块儿并发运行性能

  • 从新标记(remark)
    这个阶段是STW的,为了修正并发标记期间,因用户程序继续运做而致使标记产生变更的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但也远比并发标记阶段的时间短网站

  • 并发清除(concurrent sweep)
    清理删除掉标记阶段判断的已经死亡的对象,因为不须要移动存活对象,因此这个阶段也是能够与用户线程同时并发的线程

CMS的优势

  1. 并发收集垃圾
  2. 低延时

CMS的缺点

  1. CMS对处理器资源很是敏感。并发标记阶段吞吐量较低,虽然不会致使用户线程停顿,可是会致使应用程序变慢。由于有一部分CPU资源被分配给了垃圾收集线程4核CPU会分配25%的资源给垃圾回收线程,核数越多,分配给垃圾回收线程的资源比例占总核数比例会降低。可是当CPU不足4核的时候,原本应用负载就已经很高了,若是再分一半的资源给垃圾收集线程就会致使程序的执行速度大幅度下降设计

  2. Con-current ModeFailure 触发Full GC(STW)交由Serial Old收集器来收集。因为在垃圾收集阶段用户线程还须要持续运行,那就还须要预留足够内存空间提供给用户线程使用,所以CMS收集器不能像其余收集器那样等待到老年代几乎彻底被填满了再进行收集,必须预留一部分空间供并发收集时的程序运做使用。在JDK5的默认设置下,CMS收集器当老年代使用了68%的空间后就会被激活,这是一个偏保守的设置,若是在实际应用中老年代增加并非太快,能够适当调高参数-XX:CMSInitiatingOccu-pancyFraction的值来提升CMS的触发百分比,下降内存回收频率,获取更好的性能。但若是这个值给的太高,好比90%,这又会更容易面临另外一种风险:要是CMS运行期间预留的内存没法知足程序分配新对象的须要,就会出现一次“并发失败”(Concurrent Mode Failure),这时候虚拟机将不得不启动后备预案:冻结用户线程的执行,临时启用Serial Old收集器来从新进行老年代的垃圾收集,但这样停顿时间就很长了。因此这个参数设置得过高将会很容易致使大量的并发失败产生,性能反而下降,用户应在生产环境中根据实际应用状况来权衡设置对象

  3. 会产生内存空间碎片,分配大对象时空间不足提早触发FGC。CMS是一款基于“标记-清除”算法实现的收集器,收集结束时会有大量空间碎片产生。空间碎片过多时,将会给大对象分配带来很大麻烦,每每会出现老年代还有不少剩余空间,但就是没法找到足够大的连续空间来分配当前对象,而不得不提早触发一次Full GC。不过也能够经过设置参数尽可能的避免这个状况的发生,CMS收集器提供了一个-XX:+UseCMS-CompactAtFullCollection开关参数(默认是开启的,此参数从JDK 9开始废弃),用于在CMS收集器不得不进行Full GC时开启内存碎片的合并整理过程,因为这个内存整理必须移动存活对象,(在Shenandoah和ZGC出现前)是没法并发的。这样空间碎片问题是解决了,但停顿时间又会变长,所以虚拟机设计者们还提供了另一个参数-XX:CMSFullGCsBeforeCompaction(此参数从JDK 9开始废弃),这个参数的做用是要求CMS收集器在执行过若干次(数量由参数值决定)不整理空间的Full GC以后,下一次进入Full GC前会先进行碎片整理(默认值为0,表示每次进入Full GC时都进行碎片整理)blog

CMS特别须要注意的参数

  • -XX:CMSInitiatingOccu-pancyFraction:设置触发老年代回收的阈值,避免发生Concurrent Mode Failure引起FGC
  • -XX:+UseCMS-CompactAtFullCollection:在CMS收集器不得不进行Full GC时开启内存碎片的合并整理过程
  • -XX:CMSFullGCsBeforeCompaction

关于CMS的总结

虽然开创了并发回收垃圾的先河但因为有Con-current ModeFailure会触发FGC这个致命性的缺点,所以没有任何版本的JDK采用CMS做为默认的垃圾回收器,JDK9中CMS已经消失,但CMS并发回收垃圾的思想却一直在延续图片

相关文章
相关标签/搜索