如何调整JVM 8 G1参数以避免完全GC(分配失败)



在XMX为8 GB的服务器中使用G1 GC时,运行几天后会发生完全GC故障。

尝试多次调整JVM GC参数,并打印出所有GC详细信息,但仍然无法确定的根本原因

JVM参数:

java -Xms8g -Xmx8g 
-XX:+CrashOnOutOfMemoryError 
-XX:+AlwaysPreTouch 
-XX:-UseBiasedLocking 
-XX:MaxTenuringThreshold=15 
-Xss256k 
-XX:SurvivorRatio=6 
-XX:+UseTLAB 
-XX:GCTimeRatio=4 
-XX:+ScavengeBeforeFullGC 
-XX:G1HeapRegionSize=8M 
-XX:ConcGCThreads=8 
-XX:G1HeapWastePercent=10 
-XX:+AggressiveOpts 
-XX:MaxMetaspaceSize=256m 
-XX:+UseG1GC 
-XX:InitiatingHeapOccupancyPercent=35 
-XX:+DisableExplicitGC 
-Xloggc:/var/tmp/prod/query/Portfolio/PORTFOLIO-QRY-A-Instance1/query-gc.log
-verbose:gc 
-XX:+PrintGCDetails 
-XX:+PrintGCDateStamps 
-XX:+PrintGCTimeStamps 
-XX:+UseGCLogFileRotation 
-XX:NumberOfGCLogFiles=10 
-XX:GCLogFileSize=100M 
-XX:+HeapDumpOnOutOfMemoryError 
-XX:HeapDumpPath=/var/tmp/prod/query/xxx.log-XX:NewSize=3g 
-XX:MaxNewSize=5g 
-server

最后一次GC详细信息:

2019-01-25T0:28.998+0800:399236.910:[GC暂停(G1疏散暂停)(年轻)(初始标记)(空间耗尽),0.3400461秒]
[伊甸园:1080.0M(3072.0M)->0.0B(3072.0M)幸存者:0.0B->0.0B堆:8144.0M(8192.0M)->7936.0M并发根区域扫描开始]2019-01-25T0:29.338+0800:399237.251:[GC并发根区域扫描结束,0.0000869秒]2019-01-25T0:29.338+0800:399237.251:[GC并发标记开始]2019-01-25T0:29.419+0800:39927.332:[GC暂停(G1疏散暂停)(年轻)(到太空耗尽),0.2033834秒][伊甸园:208.0M(3072.0M)->0.0B(3072.0M)幸存者:0.0B->0.0B堆:8144.0M(8192.0M)->8144.0M(G1疏散暂停)(年轻),0.0076649秒][伊甸园:0.0B(3072.0M)->0.0B(3092.0M)幸存者:0.0B->0.0B堆:8144.0M(8192.0M)->8144.0M(G1疏散暂停)(年轻),0.0072213秒][伊甸园:0.0B(3072.0M)->0.0B(3092.0M)幸存者:0.0B->0.0B堆:8144.0M(8192.0M)->8144.0M(G1疏散暂停)(年轻),0.0032099秒][伊甸园:0.0B(3072.0M)->0.0B(307 2.0M)幸存者:0.0B->0.0B堆:8144.0M(8192.0M)->8144.0M(G1疏散暂停)(年轻),0.0041076秒][伊甸园:0.0B(3072.0M)->0.0B(307 2.0M)幸存者:0.0B->0.0B堆:8144.0M(8192.0M)->8144.0M(G1疏散暂停)(年轻),0.0027963秒][伊甸园:0.0B(3072.0M)->0.0B(3092.0M)幸存者:0.0B->0.0B堆:8144.0M(8192.0M)->8144.0M(G1疏散暂停)(年轻),0.0027614秒][伊甸园:0.0B(3072.0M)->0.0B(307 2.0M)幸存者:0.0B->0.0B堆:8144.0M(8192.0M)->8144.0M(分配失败)8144M->4016M(8192M),10.6192450秒][伊甸园:0.0B(3072.0M)->0.0B(3092.0M)幸存者:0.0B->0.0B堆:8144.0M(8192.0M)->4016.1M(8192.00M)],[元空间:83995K->83979K(1126400K)][时间:user=15.73 sys=0.00,real=10.62秒]2019-01-25T0:25:40277+0800:39248.190:[GC并发标记中止]堆垃圾第一个堆总计8388608K,已使用4268154K[0x00000005c0000000,0x00000005c0802000,0x00000007c0000000)区域大小8192K,20个年轻(163840K),0个幸存者(0K)元空间
已使用84034K,容量85146K,已提交86732K,保留1126400K
类空间已使用8833K,容量9090K,已提交9420K,保留1048576K


我们的服务器是32G16核心,任何建议或建议都将不胜感激!

这很复杂。

在日志中,我发现由于旧一代的原因,进行完整GC的次数太少了。

"分配失败"表明,对老一代的直接分配失败了。

但是,从日志中我还发现,在完全GC之前的次要GC过于频繁,并且释放了一点空间。在25:29.338和25:29.653之间有7个轻微GC只有第一个次要GC释放了一些空间。

最糟糕的问题是"[Eden:0.0B(3072.0M)->0.0B(3072.00M。这很奇怪。您的应用程序至少需要4G旧一代,并且旧一代中的几乎所有对象都被回收。这意味着旧物体不够旧。他们中的大多数人被提前提拔。或者它们中的大部分都是巨大的物体。

我试着给你一些建议。。。

  1. -XX:启动堆占用百分比=35太小它使次要GC更加频繁,并且对象可能会提前升级。所以老一代很快就会吃饱。您可以将XX:SinitiatingHeapOccupancyPercent设置得更大。或者您可以考虑自适应IHOP
  2. 老一辈太小了有些应用程序需要更多的老一代空间,而不是年轻一代空间。有人说,年轻一代的空间大小增加一倍或三倍是好的。

  3. MaxTenuringThreshold=15可以设置为大于20的值。

    • 理解g1 gc日志
    • G1收集器

最新更新