G1

497 阅读6分钟

[TOC]

G1

  1. G1垃圾回收器是可以同时回收新生代和老年代的对象的,不需要两个垃圾回收器配合起来运作,他一个人就可以搞定所有的垃圾回收。他最大的一个特点,就是把Java堆内存拆分为多个大小相等的Region。
  2. G1最大的一个特点,就是可以让我们设置一个垃圾回收的预期停顿时间。
  3. G1核心思路:G1 可以做到让你来设定垃圾回收对系统的影响,他自己通过把内存拆分为大量小Region,以及追踪每个Region中可以回收的对象大小和预估时间,最后在垃圾回收的时候,尽量把垃圾回收对系统造成的影响控制在你指定的时间范围内,同时在有限的时间内尽量回收尽可能多的垃圾对象。
  4. 在G1对应的内存模型中,Region随时会属于新生代也会属于老年代,所以没有所谓新生代给多少内存,老年代给多少内存这 一说了实际上新生代和老年代各自的内存区域是不停的变动的,由G1自动控制。

理解G1

每个Region多大:

Region的大小必须是2的倍数,比如说1MB、2MB、4MB。

新生代包含多少Region:

刚开始的时候,默认新生代对堆内存的占比是5%,也就是占据200MB左右的内存,对应大概是100个Region,这个是可以通过“-XX:G1NewSizePercent”来设置新生代初始占比的,其实维持这个默认值即可

新生代如何动态增加Region :

在系统运行中,JVM其实会不停的给新生代增加更多的Region,但是最多新生代的占比不会超过60%,可以通过“-XX:G1MaxNewSizePercent

Eden和Survivor两个区域仍然还是存在

什么时候触发新生代的垃圾回收:

随着不停的在新生代的Eden对应的Region中放对象,JVM就会不停的给新生代加入更多的Region,直到新生代占据堆大小的最大比例60%。一旦新生代达到了设定的占据堆内存的最大大小60%,比如都有1200个Region了,里面的Eden可能占据了1000个Region,每个Survivor是100个Region,而且Eden区还占满了对象,这个时候还是会触发新生代的GC

还有G1特有的预设GC停顿时间的作用

这个过程跟之前的CMS是有区别的,因为G1是可以设定目标GC停顿时间的,也就是G1执行GC的时候最多可以让系统停顿多长时间,可以通过“-XX:MaxGCPauseMills”参数来设定,默认值是200ms。

什么时候对象进入老年代:

晋升规则和 CMS 一致

大对象的独立Region存放和回收:

G1提供了专门的Region来存放大对象,而不是让大对象进入老年代的Region中, 在G1中,大对象的判定规则就是一个大对象超过了一个Region大小的50%,比如按照上面算的,每个Region是2MB,只要一个大对象超过了1MB,就会被放入大对象专门的Region中

G1

什么时候触发新生代+老年代的混合垃圾回收?

G1有一个参数,是“-XX:InitiatingHeapOccupancyPercent”,他的默认值是45%,意思就是说,如果老年代占据了堆内存的45%的Region的时候,此时就会尝试触发一个新生代+老年代一起回收的混合回收阶段。

G1垃圾回收的过程

初始标记:进入 STW 标记 GC root直接引用的对象

并发标记:这个阶段会允许系统程序的运行,同时进行GC Roots追踪,从GC Roots开始追踪所有的存活对象

最终标记:这个阶段会进入“Stop the World”,系统程序是禁止运行的,但是会根据并发标记 阶段记录的 那些对象修改,最终标记一下有哪些存活对象,有哪些是垃圾对象,

混合回收:这个阶段会计算老年代中每个Region中的存活对象数量,存活对象的占比,还有执行垃圾回 收的预期性能和效率。接着会停止系统程序,然后全力以赴尽快进行垃圾回收,此时会选择部分Region进行回收,因为必须让垃圾回收的停顿时间控制在我们指定的范围内。

举例:

比如说老年代此时有1000个Region都满了,但是因为根据预定目标,本次垃圾回收可能只能停顿200毫秒,那么通过之前的计算得 知,可能回收其中800个Region刚好需要200ms,那么就只会回收800个Region,把GC导致的停顿时间控制在我们指定的范围内

混合回收 多次

是最后一个阶段混合回收的时候,其实会停止所有程序运行,所以说G1是允许执行多次混合回收。比如先停止工作,执行一次混合回收回收掉 一些Region,接着恢复系统运行,然后再次停止系统运行,再执行一次混合回收回收掉一些Region。有一些参数可以控制这个,比如“-XX:G1MixedGCCountTarget”参数,就是在一次混合回收的过程中,最后一个阶段执行几次混合回收,默认值是8次意味着最后一个阶段,先停止系统运行,混合回收一些Region,再恢复系统运行,接着再次禁止系统运行,混合回收一些Region,反复8次。

为什么要反复回收多次呢?

因为你停止系统一会儿,回收掉一些Region,再让系统运行一会儿,然后再次停止系统一会儿,再次回收掉一些Region,这样可以尽可能让系统不要停顿时间过长,可以在多次回收的间隙,也运行一下。

回收失败时的Full GC

如果在进行Mixed回收的时候,无论是年轻代还是老年代都基于复制算法进行回收,都要把各个Region的存活对象拷贝到别的Region里去,此时万一出现拷贝的过程中发现没有空闲Region可以承载自己的存活对象了,就会触发 一次失败。一旦失败,立马就会切换为停止系统程序,然后采用单线程进行标记、清理和压缩整理,空闲出来一批Region,这个过程是极慢极慢的。

G1 调优参数

1、XX:G1MixedGCCountTarget 设置垃圾回收混合回收阶段,最多可以拆成几次回收。