JVM之G1和CMS

CMS(Concurrent Mark Sweep) 收集器

CMS 收集器是获取最短回收停顿时间为目标的收集器。适用于 B/S 系统的服务端。从名字上可以看出来是使用的标记清除算法。整个清除过程如下:

  • 初始标记(CMS initial mark) 

  • 并发标记(CMS concurrent mark)
  • 重新标记(CMS remark)
  • 并发清除(CMS concurrent sweep)

    其中初始标记和重新标记依然会停止所有的用户线程。

    初始标记仅仅是标记一下 GC Roots 能直接关联到的对象,速度很快。

    并发标记阶段就是进行 GC Roots Tracing 的过程。

    重新标记是为了修正并发标记期间,因用户程序继续运行而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般比初始标记阶段长。

    整个 GC 过程当中消耗时间最长的是并发标记和并发清除过程,但是这两个阶段的垃圾回收线程可以与用户线程一起并发执行,总体上说,CMS 收集器的内存回收过程是与用户线程一起并发执行的。

    CMS缺点:
  • CMS 对 CPU 资源敏感,在并发阶段虽然不会停止用户线程,但是会占用一部分线程来进行垃圾回收,总吞吐量会降低。
  • CMS 默认启动的线程是(CPU数量+3)/4,当 CPU 大于4个以上占用资源不超过 25% 的 CPU 资源,但是小于 4 个 CPU 时候 CMS 收集器对用户程序的影响就比较大。
  •  CMS 无法回收浮动垃圾。CMS 在并发清理阶段还可以运行用户线程,这时候还会产生新的垃圾,而这部分垃圾 CMS 无法在本次回收掉,这部分就是浮动垃圾。因此 CMS 不能像其他的收集器等到年老代几乎全部满了再进行回收,需要预留一部分空间提供并发收集时候的用户线程使用。默认设置下,CMS 收集器在年老代使用了 68% 的空间后就会被激活,可以通过 -XX:CMSInitiatingOccupancyFraction 参数来设置这个属性。如果 CMS 在运行时候预留的内存无法满足程序需要,就会出现一次“Concurrent Mode Failure”失败,这时候虚拟机临时启用 Serial Old 收集器重新来进行老年代的垃圾收集。
  • CMS 是基于标记整理算法,在清理的过程中会有大量的空间碎片。空间碎片过多后给打对象分配空间会有很多麻烦。CMS 提供了一个参数 -XX:+UseCMSCompactAtFullCollection 用来在 Full GC 完成后附加一个碎片整理过程,碎片整理无法并发会导致停顿时间变长。当然还提供了一个参数 -XX:CMSFullGCsBeforeCompaction,这个参数设置在执行多少次不压缩的 Full GC 后,跟着来一次带压缩的。 


1CMS收集器

  CMS收集器是一种以获取最短回收停顿时间为目标的收集器。基于“标记-清除”算法实现,它的运作过程如下:

1)初始标记

2)并发标记

3)重新标记

4)并发清除

  初始标记、从新标记这两个步骤仍然需要“stop the world”,初始标记仅仅只是标记一下GC Roots能直接关联到的对象,熟读很快,并发标记阶段就是进行GC Roots Tracing,而重新标记阶段则是为了修正并发标记期间因用户程序继续运作而导致标记产生表动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长点,但远比并发标记的时间短。

 

  CMS是一款优秀的收集器,主要优点:并发收集、低停顿。

缺点:

1)CMS收集器对CPU资源非常敏感。在并发阶段,它虽然不会导致用户线程停顿,但是会因为占用了一部分线程而导致应用程序变慢,总吞吐量会降低。

2)CMS收集器无法处理浮动垃圾,可能会出现“Concurrent Mode Failure(并发模式故障)”失败而导致Full GC产生。

浮动垃圾:由于CMS并发清理阶段用户线程还在运行着,伴随着程序运行自然就会有新的垃圾不断产生,这部分垃圾出现的标记过程之后,CMS无法在当次收集中处理掉它们,只好留待下一次GC中再清理。这些垃圾就是“浮动垃圾”。

3)CMS是一款“标记--清除”算法实现的收集器,容易出现大量空间碎片。当空间碎片过多,将会给大对象分配带来很大的麻烦,往往会出现老年代还有很大空间剩余,但是无法找到足够大的连续空间来分配当前对象,不得不提前触发一次Full GC。

2G1收集器

G1是一款面向服务端应用的垃圾收集器。G1具备如下特点:

1、并行于并发:G1能充分利用CPU、多核环境下的硬件优势,使用多个CPUCPU或者CPU核心)来缩短stop-The-World停顿时间。部分其他收集器原本需要停顿Java线程执行的GC动作,G1收集器仍然可以通过并发的方式让java程序继续执行。

2、分代收集:虽然G1可以不需要其他收集器配合就能独立管理整个GC堆,但是还是保留了分代的概念。它能够采用不同的方式去处理新创建的对象和已经存活了一段时间,熬过多次GC的旧对象以获取更好的收集效果。

3、空间整合:与CMS的“标记--清理”算法不同,G1从整体来看是基于“标记整理”算法实现的收集器;从局部上来看是基于“复制”算法实现的。

4、可预测的停顿:这是G1相对于CMS的另一个大优势,降低停顿时间是G1和CMS共同的关注点,但G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,

5、G1运作步骤:

1、初始标记;2、并发标记;3、最终标记;4、筛选回收

上面几个步骤的运作过程和CMS有很多相似之处。初始标记阶段仅仅只是标记一下GC Roots能直接关联到的对象,并且修改TAMS的值,让下一个阶段用户程序并发运行时,能在正确可用的Region中创建新对象,这一阶段需要停顿线程,但是耗时很短,并发标记阶段是从GC Root开始对堆中对象进行可达性分析,找出存活的对象,这阶段时耗时较长,但可与用户程序并发执行。而最终标记阶段则是为了修正在并发标记期间因用户程序继续运作而导致标记产生变动的那一部分标记记录,虚拟机将这段时间对象变化记录在线程Remenbered Set Logs里面,最终标记阶段需要把Remembered Set Logs的数据合并到Remembered Set Logs里面,最终标记阶段需要把Remembered Set Logs的数据合并到Remembered Set中,这一阶段需要停顿线程,但是可并行执行。最后在筛选回收阶段首先对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划。



- -XX:+UseParallelOldGC
- -XX:+UseConcMarkSweepGC
- -XX:+UseG1GC

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页