因为在学习JVM的垃圾回收器的过程中,发现CMS这个垃圾回收器在JDK版本中几乎没有出场,取而代之的是类似于CMS的G1收集器,这篇笔记记录下这两者的异同,以及CMS退居幕后的原因。
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。这是因为CMS收集器工作时,GC工作线程与用户线程可以并发执行,以此来达到降低收集停顿时间的目的。
CMS收集器仅作用于老年代的收集,是基于标记-清除算法的,它的运作过程分为4个步骤:
其中,初始标记、重新标记这两个步骤仍然需要Stop-the-world。初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,并发标记阶段就是进行GC Roots Tracing的过程,而重新标记阶段则是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始阶段稍长一些,但远比并发标记的时间短。
优点:并发收集、低停顿。
缺点:
CMS 在 并发标记 时是并发的,GC 线程和用户线程并发执行,这个过程可能会因为线程的交替执行而导致新产生的垃圾(即浮动垃圾)没有被标记到;而 重新标记 的作用只是修改之前并发标记所获得的不可达对象,这部分对象就是浮动垃圾。
G1重新定义了堆空间,打破了原有的分代模型,将堆划分为一个个区域。这么做的目的是在进行收集时不必在全堆范围内进行,这是它最显著的特点。区域划分的好处就是带来了停顿时间可预测的收集模型:用户可以指定收集操作在多长时间内完成。即G1提供了接近实时的收集特性。
与CMS的标记-清除算法不同,G1从整体来看是基于标记-整理算法实现的收集器,从局部(两个Region之间)上来看是基于“复制”算法实现的。但无论如何,这两种算法都意味着G1运作期间不会产生内存空间碎片,收集后能提供规整的可用内存。这种特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC。
CMS在三色标记法的实现中使用了增量更新
G1则使用了原始快照
CMS基于原来的年代分代模型
G1使用了新的基于Region模型,分为老年代Region、新生代Region、Humongous Region
因为G1引入了Region模型,所以在跨代引用中G1需要记录每个Region中的每个区域的跨代引用情况,对比CMS需要更大的内存空间进行存放记忆集,导致内存占用比较大。