垃圾收集- Java CMS被忽略,而得到完整的GC代替



我正在运行一个Java服务器,它使用CMS作为常驻收集器。在负载测试下运行时,我每隔15秒看到一次年轻的集合,每隔5米看到一次长期的(并发的)集合。这很好。

当我以大约1/2容量的实际流量运行时,我大约每隔45秒得到一个年轻集合和一个年老集合。平行,让世界停止!)大约每隔7米。为什么JVM决定执行全停止收集而不是使用CMS收集器?

从GC .log中,你可以看到"Full GC"正在运行,并且需要3秒才能完成。这里没有并发模式故障。

1350.596: [GC 1350.596: [ParNew
Desired survivor size 119275520 bytes, new threshold 3 (max 3)
- age   1:   34779376 bytes,   34779376 total
- age   2:   17072392 bytes,   51851768 total
- age   3:   24120992 bytes,   75972760 total
: 1765625K->116452K(1864192K), 0.1560370 secs] 3887120K->2277489K(5009920K), 0.1561920 secs] [Times: user=0.40 sys=0.04, real=0.16 secs] 
1355.106: [GC 1355.107: [ParNew
Desired survivor size 119275520 bytes, new threshold 3 (max 3)
- age   1:   44862680 bytes,   44862680 total
- age   2:   20363280 bytes,   65225960 total
- age   3:   16908840 bytes,   82134800 total
: 1747684K->123571K(1864192K), 0.1068880 secs] 3908721K->2307790K(5009920K), 0.1070130 secs] [Times: user=0.29 sys=0.04, real=0.11 secs] 
1356.106: [Full GC 1356.106: [CMS: 2184218K->1268401K(3145728K), 3.0678070 secs] 2682861K->1268401K(5009920K), [CMS Perm : 145090K->145060K(262144K)], 3.0679600 secs] [Times: user=3.05 sys=0.02, real=3.07 secs] 
1361.375: [GC 1361.375: [ParNew
Desired survivor size 119275520 bytes, new threshold 3 (max 3)
- age   1:   33708472 bytes,   33708472 total
: 1631232K->84465K(1864192K), 0.0189890 secs] 2899633K->1352866K(5009920K), 0.0191530 secs] [Times: user=0.19 sys=0.00, real=0.02 secs] 
1365.587: [GC 1365.587: [ParNew
Desired survivor size 119275520 bytes, new threshold 3 (max 3)
- age   1:   33475320 bytes,   33475320 total
- age   2:   22698536 bytes,   56173856 total
: 1715697K->67421K(1864192K), 0.0229540 secs] 2984098K->1335822K(5009920K), 0.0231240 secs] [Times: user=0.25 sys=0.00, real=0.03 secs] 
以下是JVM标志:
-server -Xss256K -Xms5120M -Xmx5120M -XX:NewSize=2048M -XX:MaxNewSize=2048M
-XX:SurvivorRatio=7 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
-XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=80
-XX:+UseCMSInitiatingOccupancyOnly -XX:CMSFullGCsBeforeCompaction=1
-XX:SoftRefLRUPolicyMSPerMB=73 -verbose:gc -XX:+PrintGCDetails
-XX:+PrintGCTimeStamps -XX:+PrintTenuringDistribution -Xloggc:logs/gc.log
-XX:MaxPermSize=256m -XX:PermSize=256m -XX:MaxTenuringThreshold=3

如果存活空间不够大,则可能触发Full GC。(它似乎在抱怨生还率)

要么你需要降低你的存活比率,要么一个更好的解决方案可能是增加你的NewSize,以便更少的对象从伊甸园空间存活。我有一个6 GB的伊甸园空间;)

我似乎记得去年在调优大型堆以避免完全GC时看到过类似的现象。我觉得你应该减小eden的大小。这和老一代人相比是相当大的。

我相信可能会发生的是,你的伊甸园在你的1/2速度流量下会比在全速(它们无法生存)下更"老"。这意味着更多的人需要立即转移到终身职位。如果那个时候不合适,它可能会触发一个完整的GC来腾出空间。

作为参考,这里是我们现在使用的6GB到24GB堆:

-XX:NewRatio=4 -XX:SurvivorRatio=8 -XX:+UseCompressedOops
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+DisableExplicitGC  
-XX:+UseCMSInitiatingOccupancyOnly -XX:+CMSClassUnloadingEnabled  
-XX:+CMSScavengeBeforeRemark -XX:CMSInitiatingOccupancyFraction=68
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:logs/gc.log

和你的已经很相似了。使用所有比率的好处是,您可以轻松地更改堆大小,并且(通常)可以适当地缩放。另一个注意事项是,-XX:+UseCompressedOops通常可以通过将64位寻址减少到32位(最多只能使用32GB)来减少40%的内存。

最新更新