jvm G1 无法触发mixed gc (InitiatingH

2022-08-19  本文已影响0人  一天的

1.现象

发现某线上服务(jdk1.8、G1算法),old区只在fullgc阶段回收(也就是说没有触发mixed gc)

如下图所示,虽然平时都进行gc,但是old区没有减少,只有fullgc的时候,old区才被回收

线上服务对应的gc参数为:

-XX:InitiatingHeapOccupancyPercent=70  -XX:G1NewSizePercent=40

2.G1

G1核心逻辑:

通过将内存划分若干个Region区域,可以做到gc时只回收部分内存,同时借助多核加速Region回收速度。将停顿时间变得可预测(通过调整回收内存大小,控制gc时间)、避免了内存碎片

old区和young区大小处于动态变化过程中,根据预测算法,结合-XX:MaxGCPauseMillis参数,动态调整两者内存比例,以及mixed gc回收old比例,将gc停顿时间尽可能控制在参数以内

G1中主要存在3种gc算法:

Young GC:选定所有年轻代里的Region。G1是通过调整年轻代大小,控制年轻代Region数量来控制YGC的开销。

Mixed GC:选定所有年轻代里的Region,外加根据global concurrent marking统计得出收集收益高的部分老年代Region,在用户指定的停顿时间目标范围内尽可能选择收益高的老年代Region回收,G1就是通过控制回收老年代Region数量来控制Mixed GC的开销的。

FullGC:Serial Old GC

只有Mixed gc 和Full gc会回收old区

在G1中有关键的3个参数:

-XX:InitiatingHeapOccupancyPercent:默认值45,超过这个值,开始触发全局标记,进而触发mixed gc,注意这个值表示的是:老年区已使用空间/整个堆空间

-XX:G1NewSizePercent:默认值5%,新生代最小值

-XX:G1MaxNewSizePercent:默认值60%,新生代最大值

3.InitiatingHeapOccupancyPercent之坑

当时线上的gc参数配置如下:

-XX:InitiatingHeapOccupancyPercent=70  -XX:G1NewSizePercent=40

可以发现问题:

XX:G1NewSizePercent = 40 (young区占用40%)导致 old区最多有 60%的空间,无法达到 -XX:InitiatingHeapOccupancyPercent=70,永远触发不了全局标记、mixedgc了,导致老年代回收不了,一直挤压等到fullgc,才能回收old区

相关的问题,也被提给jdk官方:

https://bugs.openjdk.org/browse/JDK-8151176

https://bugs.openjdk.org/browse/JDK-8142484

可以看到这个问题,在高版本的jdk9,已经被修复,不存在这个问题了。但是使用低版本的jdk,还要注意这个坑

4. 验证

我们将gc参数调整为:

-XX:InitiatingHeapOccupancyPercent=40  -XX:G1NewSizePercent=10 -XX:G1MaxNewSizePercent=35

将young区控制在35%以下,上线效果如下,可以看到老年代不在持续增加,会跟随mixed gc回收,不在触发fullgc(会导致较长的STW,以及oom)

上一篇 下一篇

猜你喜欢

热点阅读