阅读 740
JVM收集器CMS与G1区别和优缺点分析

JVM收集器CMS与G1区别和优缺点分析

这是我参与更文挑战的第20天,活动详情查看: 更文挑战

前言:

最近因为项目GC太频繁一直在优化项目,从新温习一下GC垃圾收集器,随着Java的迭代GC收集器也在不断的优化,今天主要给大家介绍一下CMS和G1这俩种收集器的并分析一下俩种收集器的优缺点;

CMS收集器:

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器,基于并发“标记清理”实现,在标记清理过程中不会导致用户线程无法定位引用对象。仅作用于老年代收集。它的步骤如下:

  1. 初始标记(CMS initial mark):独占CPU,stop-the-world, 仅标记GCroots能直接关联的对象,速度比较快;
  2. 并发标记(CMS concurrent mark):可以和用户线程并发执行,通过GCRoots Tracing 标记所有可达对象;
  3. 重新标记(CMS remark):独占CPU,stop-the-world, 对并发标记阶段用户线程运行产生的垃圾对象进行标记修正,以及更新逃逸对象;
  4. 并发清理(CMS concurrent sweep):可以和用户线程并发执行,清理在重复标记中被标记为可回收的对象。

优点:

  • 支持并发收集.
  • 低停顿,因为CMS可以控制将耗时的两个stop-the-world操作保持与用户线程恰当的时机并发执行,并且能保证在短时间执行完成,这样就达到了近似并发的目的.

缺点:

  • CMS收集器对CPU资源非常敏感,在并发阶段虽然不会导致用户线程停顿,但是会因为占用了一部分CPU资源,如果在CPU资源不足的情况下应用会有明显的卡顿。
  • 无法处理浮动垃圾:在执行‘并发清理’步骤时,用户线程也会同时产生一部分可回收对象,但是这部分可回收对象只能在下次执行清理是才会被回收。如果在清理过程中预留给用户线程的内存不足就会出现‘Concurrent Mode Failure’,一旦出现此错误时便会切换到SerialOld收集方式。
  • CMS清理后会产生大量的内存碎片,当有不足以提供整块连续的空间给新对象/晋升为老年代对象时又会触发FullGC。且在1.9后将其废除。

使用场景

它关注的是垃圾回收最短的停顿时间(低停顿),在老年代并不频繁GC的场景下,是比较适用的。

G1收集器

G1收集器的内存结构完全区别于CMS,弱化了CMS原有的分代模型(分代可以是不连续的空间),将堆内存划分成一个个Region(1MB~32MB, 默认2048个分区),这么做的目的是在进行收集时不必在全堆范围内进行。它主要特点在于达到可控的停顿时间,用户可以指定收集操作在多长时间内完成,即G1提供了接近实时的收集特性。它的步骤如下:

  1. 初始标记(Initial Marking):标记一下GC Roots能直接关联到的对象,伴随着一次普通的Young GC发生,并修改NTAMS(Next Top at Mark Start)的值,让下一阶段用户程序并发运行时,能在正确可用的Region中创建新对象,此阶段是stop-the-world操作。
  2. 根区间扫描,标记所有幸存者区间的对象引用,扫描 Survivor到老年代的引用,该阶段必须在下一次Young GC 发生前结束。
  3. 并发标记(Concurrent Marking):是从GC Roots开始堆中对象进行可达性分析,找出存活的对象,这阶段耗时较长,但可与用户程序并发执行,该阶段可以被Young GC中断。
  4. 最终标记(Final Marking):是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录,虚拟机将这段时间对象变化记录在线程Remembered Set Logs里面,最终标记阶段需要把Remembered Set Logs的数据合并到Remembered Set中,此阶段是stop-the-world操作,使用snapshot-at-the-beginning (SATB) 算法。
  5. 筛选回收(Live Data Counting and Evacuation):首先对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划,回收没有存活对象的Region并加入可用Region队列。这个阶段也可以做到与用户程序一起并发执行,但是因为只回收一部分Region,时间是用户可控制的,而且停顿用户线程将大幅提高收集效率。

G1的特点

  • 并行与并发:G1充分发挥多核性能,使用多CPU来缩短Stop-The-world的时间,
  • 分代收集:G1能够自己管理不同分代内已创建对象和新对象的收集。
  • 空间整合:G1从整体上来看是基于‘标记-整理’算法实现,从局部(相关的两块Region)上来看是基于‘复制’算法实现,这两种算法都不会产生内存空间碎片。
  • 可预测的停顿:它可以自定义停顿时间模型,可以指定一段时间内消耗在垃圾回收商的时间不大于预期设定值。

使用场景

G1 GC切分堆内存为多个区间(Region),从而避免很多GC操作在整个Java堆或者整个年轻代进行。G1 GC只关注你有没有存货对象,都会被回收并放入可用的Region队列。G1 GC是基于Region的GC,适用于大内存机器。即使内存很大,Region扫描,性能还是很高的。

ok!今天的文章就到这了,希望可以对大家有帮助,有不对的地方希望大家可以提出来的,共同成长;

整洁成就卓越代码,细节之中只有天地

文章分类
后端
文章标签