CMS收集器与G1收集器

CMS(Concurrent Mark Sweep):

        以获取最短回收停顿时间为目标的收集器,是基于“标记-清除”算法的,整个四个步骤包括:

        (1)初始标记  (2)并发标记 (3)重新标记 (4)并发清除

       初始标记和重新标记仍需要"Stop The World"(暂停工作线程),初始标记仅仅标记下GC Roots能直接关联到的对象,速度很快,并发标记阶段就是进行GC Roots Tracing的过程,而重新标记阶段则是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记稍长一些,但远比并发标记的时间短,由于整个过程中耗时最长的并发标记和并发清除过程收集器线程都可以与用户线程一起工作,所以,从总体上说,CMS收集器的内存回收过程是与用户线程一起并发执行的。

       CMS的优点:并发收集、低停顿

       CMS收集器有3个明显的缺点:

        1.CMS收集器对CPU资源非常敏感:CMS默认启动的回收线程数是 (CPU数量+3)/4 ,也就是CPU在4个以上时,并发回收的垃圾收集线程不少于25%的CPU资源,并且随着CPU数量的增加而下降,(CPU数量+3)/4  /  CPU数量 = (1+3/CPU数量)/4>=25%

当CPU数量不足4个时,例如2,CMS对用户程序的影响可能变得很大,如果本来CPU负载就比较大,再分出一般的运算能力去执行收集器线程,可能导致用户的执行速度突然降低了50%,为了应付这种情况,虚拟机提供了一种“增量式并发收集器”的CMS收集器变种,就是在并发标记、清理的时候让GC线程、用户线程交替执行,尽量减少GC线程独占CPU资源的时间,这样整个垃圾收集的过程会更长,但对用户程序的影响就会显得少一点,速度下降没有那么明显,但是效果一般

         2.CMS收集器无法处理并发清理阶段用户程序产生的垃圾(浮动垃圾):这样由于垃圾回收阶段用户线程仍在运行,所以必须预留出一定的空间,也就是CMS不能像其他垃圾回收器在堆满才进行回收,如果中间出现用户线程内存空间不够可能会出现"Concurrent Mode Failure"触发另一次Full GC的产生,失败后会启用备用垃圾回收器Serial Old,这样停顿事务时间就比较长了。

         3.CMS容易出现内存碎片:因为CMS是基于"标记-清除"的,所以会产生很多内存碎片,只有在要进行Full GC时开启内存碎片的合并整理过程,内存整理是无法并发进行的,空间碎片没有问题了,但是停顿时间不得不变长。

G1收集器:

G1:面向服务端应用的垃圾收集器

优势:

1.同CMS一样,用户线程和垃圾回收线程同时运行

2.整体基于"标记-整理"算法,局部基于复制算法,收集后不会产生空间碎片

3.可预测的停顿:一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不超过N毫秒

G1的内存布局是将整个Java堆划分为多个大小相等的独立区域,虽然还保留新生代和老生代的概念,但是新生代老生代物理上不在是隔离的,它们都是一部分region的集合

阶段:初始标记、并发标记、最终标记、筛选回收  其中初始标记、最终标记、筛选回收需要用户线程停顿

最终标记:为了修正并发期间因用户程序继续运行而导致标记产生变动的那一部分标记记录,虚拟机将这段时间对象变化记录到线程的Remembered Set Logs里面,最终标记阶段需要把Remembered Set Logs数据合并到Remembered Set中,这阶段需要停顿线程,但是可并行执行。

筛选回收:首先对各个Region中的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划,停顿用户线程只回收一部分region提高回收效率

G1跟踪各个region里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先队列,每次根据允许的收集时间,优先回收价值最大的Region这也是Garbage-first名称的由来),这种使用Region划分内存空间以及优先级的区域回收方式,保证了G1收集器在有限的时间内可以获得尽可能高的收集效率

每个Region都有一个Remembered Set,用来记录该Region对象的引用对象所在的region,通过使用Remembered Set,在做可达性分析的时候可以避免全堆扫描

猜你喜欢

转载自blog.csdn.net/qq_27378875/article/details/81383221