关于 G1(Garbage First)垃圾收集器

Posted 流楚丶格念

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于 G1(Garbage First)垃圾收集器相关的知识,希望对你有一定的参考价值。

文章目录

G1收集器

概念

G1(Garbage First)是一款主要面向服务端应用的垃圾收集器,JDK 9发布之日,G1宣告取代ParallelScavenge加Parallel Old组合,成为服务端模式下的默认垃圾收集器,而CMS则沦落至被声明为不推荐使用(Deprecate)的收集器。

G1收集器是垃圾收集器技术发展历史上的里程碑式的成果,它开创了收集器面向局部收集的设计思路和基于Region的内存布局形式。

设计思路

虽然G1也仍是遵循分代收集理论设计的,但其堆内存的布局与其他收集器有非常明显的差异:

  • G1不再坚持固定大小以及固定数量的分代区域划分,而是把连续的Java堆划分为多个大小相等的独立区域(Region),每一个Region都可以根据需要,扮演新生代的Eden空间、Survivor空间,或者老年代空间

收集器能够对扮演不同角色的Region采用不同的策略去处理,这样无论是新创建的对象还是已经存活了一段时间、熬过多次收集的旧对象都能获取很好的收集效果

设计原理

Region中还有一类特殊的Humongous区域,专门用来存储大对象。G1认为只要大小超过了一个Region容量一半的对象即可判定为大对象

每个Region的大小可以通过参数 -XX:G1HeapRegionSize设定,取值范围为1MB~32MB,且应为2的N次幂。

而对于那些超过了整个Region容量的超级大对象,将会被存放在N个连续的 Humongous Region 之中,G1的大多数行为都把 Humongous Region 作为老年代的一部分来进行看待

如下图所示:

虽然G1仍然保留新生代和老年代的概念,但新生代和老年代不再是固定的了,它们都是一系列区域(不需要连续)的动态集合。

G1收集器之所以能建立可预测的停顿时间模型,是因为它将Region作为单次回收的最小单元,即每次收集到的内存空间都是Region大小的整数倍,这样可以有计划地避免在整个Java堆中进行全区域的垃圾收集。

更具体的处理思路是让G1收集器去跟踪各个Region里面的垃圾堆积的“价值”大小,价值即回收所获得的空间大小以及回收所需时间的经验值,然后在后台维护一个优先级列表,每次根据用户设定允许的收集停顿时间(使用参数-XX:MaxGCPauseMillis指定,默认值是200毫秒),优先处理回收价值收益最大的那些Region,这也就是“Garbage First”名字的由来。这种使用Region划分内存空间,以及具有优先级的区域回收方式,保证了G1收集器在有限的时间内获取尽可能高的收集效率。

执行步骤:

如果我们不去计算用户线程运行过程中的动作,G1收集器的运作过程大致可划分为以下四个步骤:

  • 初始标记: 仅仅是标记一些GC Roots能直接关联到的对象,并且修改TAMS指针的值,让下一阶段用户线程并发运行时,能正确地在可用的Region中分配新的对象。
  • 并发标记: 从GC Roots开始对堆中对象进行可达性分析,递归扫描整个堆里的对象图,找出要回收的对象,与用户线程并发执行。
  • 最终标记: 对用户线程做另一个短暂的暂停,用于处理并发阶段结束后仍遗留下来的最后那少量的SATB记录。
  • 筛选回收: 负责更新Region的统计数量,对各个Region进行回收价值和成本排序,根据用户期望的停顿时间制定回收计划,然后把决定回收的那一部分Region的存活对象复制到空的Region中,再清理掉整个旧的Region的全部空间。

下面是G1收集器的运行示意图:

以上是关于关于 G1(Garbage First)垃圾收集器的主要内容,如果未能解决你的问题,请参考以下文章

Garbage First(G1)垃圾收集器

详解 JVM Garbage First(G1) 垃圾收集器

Garbage First(G1) 垃圾收集器

[JVM 相关] Java 新型垃圾回收器(Garbage First,G1)

JVM垃圾回收器之G1(Garbage First)--new

用了很多年的 CMS 垃圾收集器,终于换成了 G1,真香!!