我有一个 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
如果您不设置这些,那么什么时候是开始使用“指标”的好时机
My understanding is that a tenured collection should only occur when old gen is nearly full;
这就是并行收集器的作用。
关于java - 终身 Collection 无明显原因启动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26107171/