Garbage First——G1垃圾回收器

Garbage First俗称G1,2004年被提出,2006年JDK6体验,2012年JDK7.0官方支持,再到2017年JDK9默认的垃圾回收器。在JDK9中废弃了CMS垃圾回收器,从而说明G1取代了CMS垃圾回收器。

G1同时注重吞吐量和低延迟,也属于并发的垃圾回收器。G1也适合超大堆内存,将堆内存划分为多个大小相等的Region,每个区域都是1、2、4、8M的大小,每个区域都可以独立的作为伊甸园、幸存区、老年代,这个区域的大小可以通过-XX:G1HeapRegionSize=size(Size必须为1、2、4、8、16),堆内存过大,那对应的回收速率就会越来越慢,因为涉及到对象的赋值,而把整个分为小的区域进行管理,化整为零,这样可以进行优化,加快标记和拷贝的速率。整体上G1使用了标记+整理算法,但是两个区域之间使用了复制算法。在JDK1.8中G1是默认关闭的,所以需要使用命令-XX:+UseG1将G1垃圾回收器打开。

垃圾回收阶段

Oracle JVM工程师将G1的垃圾回收阶段分为三个阶段:Young Collection(新生代的垃圾收集)、Young Collection+Concurrent Mark(新生代的垃圾收集,并且执行一些并发标记)、MixedCollection(混合收集),这三个阶段是一个循环的过程,刚开始新生代的垃圾收集,当老年代的内存超过一个阈值时,会在新生代垃圾收集时,进行并发标记,等这个阶段完成后会进行一个混合收集,混合收集就是对新生代、幸存区、老年代都来进行一个规模较大的收集,等混合收集结束后,伊甸园的内存就会被释放,然后会再次进入新生代的垃圾收集。

Oracle工程师对于JVM的说法

在上面提到过G1回收器会将堆内存划分为大小相等的一个区域,每个区域都可以独立的作为伊甸园、幸存区和老年代,如下图所示,刚开始白色的区域就是一个空闲的区域,当白色空闲区域被占满,会触发一次新生代的垃圾回收,会触发一个STW。

新生代内存布局

 

G1垃圾回收的第二阶段:新生代的垃圾回收和并发标记阶段(Young Collection+CM)。在进行垃圾回收的过程中,就要对GC Root对象进行初始标记和并发标记。初始标记就是找到那些根对象,而并发标记是指沿着根对象找到其他对象并标记。初始标记是在新生代GC时执行,初始标记并不会占用我们并发标记的时间,仅仅发生在新生代的垃圾回收时。当老年代占用堆空间比例达到一定阈值时才会发生并发标记(不会造成其他用户线程暂停,即不会STW),而这里的阈值可以通过一个JVM参数来控制——-XX:InitiatingHeapOccupancyPercent=percent(默认为45%)。

G1垃圾回收的第三个阶段:Mixed Collection。在这个阶段会对E、S、O三个区域进行全面的垃圾回收。如下图所示,伊甸园幸存的对象会通过复制算法复制到幸存区中,另一些幸存区不够年龄的也会被重新复制到新的幸存区中,有些符合晋升条件的会直接复制到老年代中去,这些都属于新生代的垃圾回收。还有一部分老年代的区域,也经过了标记并发阶段,发现有些对象已经没有用了,但是这个时候G1垃圾回收器会根据最大暂停时间有选择的进行回收,下面只有两个红色的老年代进行回收,其他的则没有,因为有的时候堆内存的空间太大,这个时候老年代的垃圾回收时间会比较长,就达不到最大暂停时间,为了要达到这个时间,G1就会从这些老年代中挑选那些回收价值较高的几个区域,也就是这个区域回收了就会释放更多的空间。所以这也说明了为什么叫Garbage First?是因为它会在这个环节优先回收那些垃圾较多的区域。在混合收集的各个阶段有最终标记、拷贝存活都会STW,

 

猜你喜欢

转载自blog.csdn.net/qq_35363507/article/details/105079951
今日推荐