JVM垃圾收集器-CMS收集器

CMS收集器

       CMS收集器是一种以获取最短回收停顿时间为目标的收集器,目前很大一部分的Java应用都集中在互联网或B/S系统都服务端上,这类应用尤其重视服务的响应速度,希望系统停顿时间最短,以给用户带来较好的体验。CMS收集器就非常符合这类应用的需求。

      它是基于“标记-清除“算法实现的,它的运作过程相对于前几种收集器较复杂点,整个过程分为4步,包括:初始标记,并发标记,重新标记,并发清除,其中初始标记、重新标记这两步仍然需要“Stop The World”。初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,并发标记阶段就是进行GC Roots Tracing的过程,而重新标记阶段是为了修正并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。

     由于整个过程中耗时最长的并发标记和并发清除过程中,收集器线程都可以与用户线程一起工作,所以总体上来说,CMS收集器的内存回收过程是与用户线程一起并发地执行的,如下图:

      

        CMS是一款优秀的收集器,它的最主要优点在名字上已经体现出来来:并发收集、低停顿,Sun的一些官网文档里面也称为并发低停顿收集器。它也存在显著的缺点:

        CMS收集器对CPU资源非常敏感。在并发阶段,它虽然不会导致用户线程停顿,但是会因为占用来一部分线程而导致应用程序变慢,总吞吐量会降低。CMS默认启用的回收线程数(CPU数量+3)/4,也就是当CPU在4个以上时,并发回收时垃圾收集线程最多占用不超过25%的CPU资源。但是当CPU不足4个时,那么CMS对用户程序的程序就可以变得很大,如果CPU负载本来就比较大的时候,还要分出一半的运算能力去执行收集器线程,就可以导致用户程序的执行速度忽然降低来50%,这很让人受不了,为来解决这种情况,虚拟机提出来一种称为“增量式并发收集器”的CMS收集器变种,所做的事情和单CPU年代PC机操作系统使用抢占式爱模拟多任务机制的思想一样,就是在并发标记和并发清理的时候让GC线程、用户线程交替运行,尽量减少GC线程的独占资源的时间,这样整个垃圾收集的过程会更长。

       CMS收集器无法处理浮动垃圾,可能出现“Concurrent Mode Failure“失败而导致另一次Full GC。由于CMS并发清理阶段用户线程还在运行着,伴随程序的运行自然还会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS无法在本次收集中处理掉它们,只好留待下一次GC时再将其清理掉。这一部分垃圾就被称为”浮动垃圾“。

       CMS收集器收集结束后会产生大量的空间碎片。空间碎片过多时,将会给大对象分配带来很大的麻烦,往往会出现老年代还有很大的空间剩余,但是无法找到足够大的连续空间来分配当前对象,不得不提前触发一次Full FG。为了解决这个问题,CMS收集器提供了一个-XX:+UseCMSCompactAtFullCollection开关参数,用于在“享受”完Full GC服务之后额外免费附送一个碎片整理过程,内存整理的过程是无法并发的,空间碎片问题没有了,但停顿时间不得不变长了。虚拟机设计者们还提供了另外一个参数-XX:CMSFullGCsBeforeCompaction,这个参数用于设置在执行多少次不压缩但Full GC后,跟着来一次带压缩。

        

猜你喜欢

转载自blog.csdn.net/yin4302008/article/details/86486671