我有一个Java应用程序,该应用程序通常具有非常健康的垃圾回收统计信息。租期收集通常每隔一个小时左右发生一次,而STW部分只需几分之一秒。但是奇怪的是,集合总是在应用启动的前五分钟之内发生。这是一个真正的问题,因为当时CPU使用率已经比正常情况高得多(由于最终会缓存更多的网络调用),所以这些暂停总是比正常情况更长,甚至如果我正在执行,则运行超过8秒在极重的负载下重启。
这是JVM参数:
-Xms4096m
-Xmx4096m
-XX:PermSize=768m
-XX:MaxPermSize=768m
-XX:SurvivorRatio=6
-XX:NewSize=1024m
-verbose:gc
-XX:-DisableExplicitGC
-XX:+PrintGCDetails
-XX:+PrintGCApplicationStoppedTime
-XX:+PrintGCTimeStamps
-XX:+PrintHeapAtGC
-XX:+PrintTenuringDistribution
-XX:+HeapDumpOnOutOfMemoryError
-XX:MaxDirectMemorySize=2048m
-XX:+UseConcMarkSweepGC
-XX:+CMSClassUnloadingEnabled
-XX:+PrintConcurrentLocks
-XX:+ExplicitGCInvokesConcurrent
这里的问题是,什么触发了这个永久性的收集,因为当它发生时,旧一代中几乎有2gb的空闲空间。这是租用的收藏集在一般情况下的正常使用情况:
concurrent mark-sweep generation total 3145728K, used 2897098K
这是在启动前几分钟内触发永久性收集之前的用法:
concurrent mark-sweep generation total 3145728K, used 1573655K
我的理解是,仅当旧世代快满了时,才应进行终身收藏。否则会触发什么?
最佳答案
CMS的一个关键概念是,它应在空间不足之前开始收集,从而允许它同时运行。如果它等到您用完了,就会触发一个序列停止世界收藏。
因此,有两个阈值来确定何时过早触发收集。
-XX:CMSInitiatingOccupancyFraction=90 (by default)
-XX+UseCMSInitiatingOccupancyOnly
如果您不设置这些参数,那么在开始使用“指标”的时候就可以解决问题
我的理解是,仅当旧世代快满了时,才应进行终身收藏。
这就是Parallel Collector所做的。