主打:低延迟
一、概述
a、在jdk1.5时期,HotSpot推出了一款强交互应用中几乎可以认为有划时代意义的垃圾收集器
CMS(Concurrent-Mark-Sweep)收集器,这款收集器是HotSpot虚拟机中第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程同时工作。
b、CMS收集器的关注点是尽可能缩短垃圾收集时用户线程停顿时间,停顿时间越短(低延迟)就越适合与用户交互的程序,良好的响应速度能提升用户体验。
目前很大一部分的java应用集中在互联网或者B/S系统的服务端上,这类应用尤其重视服务的相应速度,希望系统停顿时间最短。,以给用户带来较好的体验CMS收集器就非常否和这类应用的需求。
c、CMS的垃圾收集算法采用标记-清除算法,并且也会“Stop-the-world”
d、不幸的是,CMS作为老年代的收集器,却无法与jdk1.4.0中已经存在的新生代收集器Parallel Scavenge 配合工作,所以在jdk1.5使用CMS来收集老年代的时候,新生代只能选择ParNew或者Serial收集器中的一个。
在G1出现之前,CMS使用还是非常广泛的。一直到今天,仍然有很多系统使用CMS GC
二、工作原理:
a、图解:
文字说明:
CMS整个过程比之前的收集器要复杂,整个过程为4个主要阶段,即初始标记阶段,并发标记阶段,重新标记阶段和并发清除阶段。
a、初始标记(Initial—Mark)阶段:在这个阶段中,程序中所有的工作线程都将会因为“Stop-the-world”机制而出现短暂的暂停,这个阶段的主要任务仅仅是标记除GC Roots能直接关联到的对象。一旦标记完成之后就会恢复之前被暂停的所有应用线程,由于直接关联对象表较小,所以这里的速度非常快。
b、并发标记(Concurrent-Mark)阶段:从GC Roots的直接关联对象开始遍历整个对象图的过程,这个过程耗时较长,但是不需要停顿用户线程,可以与垃圾收集线程一起并发运行。
c、重新标记(Remark)阶段:由于在并发标记阶段中,程序的工作线程会和垃圾收集线程同时运行或者交叉运行,因此为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间通常会比初始标记阶段稍微长一些,但也远比并发标记阶段的时间端。
d、并发清除(Concurrent-Sweep)阶段:此阶段清理删除掉标记阶段判断已经死亡的对象,释放内存空间,由于不需要移动存活的对象,所以这个阶段也是可以与用户线程同时并发的
三、CMS的低延迟
四、MarkSweep会造成内存碎片,为什么不把算法换成Mark Compact呢?
因为当并发清除的时候,用Compact整理内存的话,原来用户线程使用的内存还怎么用呢?要保证用户线程能继续执行,前提的它运行的资源不受影响嘛,Mark Compact更合适“Stop the World”这种场景下的使用。
五、优缺点:
优点:
a、并发收集
b、低延迟
缺点:
a、会产生内存碎片,导致并发清除后,用户线程可能的空间不足,无法分配大对象的情况下,不得不提前出发Full GC。
b、CMS收集器对CPU资源非常敏感,在并发阶段,它虽然不会导致用户停顿,但是因为占用了一部分线程而导致应用程序变慢,总的吞吐量降低。
c、CMS收集器无法处理浮动垃圾。可能出现“Concurrent Mode Failure”失败而导致另一次Full GC的产生。在并发标记阶段由于线程的工作线程和垃圾线程是同时运行或者交叉运行的,那么在并发标记阶段如果产生新的垃圾对象,CMS将无法对这些垃圾进行标记,最终会导致这些新产生的垃圾对象没有被及时回收,从而只能在下一次执行GC时释放这些之前违背回收的内存空间。
重新标记只是修正的是以前是垃圾对象,但不确定,确定一下。
六、参数设置:
ParallelGC 默认是CPU的个数。