25、JVM实战:垃圾收集器:G1

19.7–垃圾收集器–G1


1、结构图

*

2、G1收集器(面向服务端)

*

2.1、特点

2.1.1、并行于并发

使用多个CPU(CPU或者CPU核心)来缩短stop-The-World停顿时间,其他需要停顿Java线程执行的GC动作,G1收集器仍然可以通过并发的方式让java程序继续执行。

2.1.2、分代收集

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

2.1.3、空间整合

与CMS的"标记–清理"算法不同,G1从整体来看是基于"标记整理"算法实现的收集器;从局部上来看是基于"复制"算法实现的。

但无论如何,都意味着G1运作期间不会产生内存空间碎片,收集后能够提供规整的可用内存,这种特性有利于程序长时间运行,分配大对象时不会因为无法找到连续内存空间而提前触发下一次GC。

2.1.4、可预测的停顿

这是G1相对于CMS的另一大优势,降低停顿时间是G1和CMS共同关注点, 但G1除了追求低停顿外,还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N毫秒。

2.2、存储内存结构

1、 G1会将堆划分为固定大小的多个区域,名称为Region;
2、 每一个Region都有对应一个rememberedset(避免全堆扫描,记录每个对象是否可达);
3、 依然存在eden,S0,S1,old这些概念,不同的是是采用逻辑区分,而不是物理区分;
4、 每个heap区(Region)的大小在JVM启动时就确定了,JVM通常生成2000个左右的heap区;
5、 根据堆内存的总大小,一个Region的大小可以通过参数-XX:G1HeapRegionSize设定,范围允许为1Mb到32Mb,且是2的指数倍;

*

2.3、优先列表

G1跟踪各个region里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region。

这种使用Region划分内存空间以及有优先级的区域回收方式,保证了G1收集器在有限的时间内可以获取尽可能高的收集效率。

2.4、收集步骤

2.4.1、标记标记(Initial Marking)

停顿用户,耗时很短,只是标记一下GC Roots能直接关联到的对象,并且修改TAMS(Next Top At Mark Start)的值,让下一个阶段用户程序并发运行时,能在正确可用的Region中创建新对象。

2.4.2、并发标记(Concurrent Marking)

GCRoot开始对堆中对象进行可达性分析,找出存活的对象,这阶段时耗时较长,但可与用户程序并发执行。

2.4.3、终标记阶(Final Marking)

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

这一阶段需要停顿线程,但是可并行执行。

2.4.4、筛选回收

首先对各个Region的回收价值和成本进行排序,根据用户所期望的GC停顿时间来制定回收计划。