2014-09-29 37 views
0

我有一个Java应用程序,通常有非常健康的垃圾收集统计。终身收藏通常每隔一小时左右发生一次,STW部分只需要几分之一秒。但奇怪的是,收集总是在应用程序启动的前五分钟内发生。这是一个真正的问题,因为那时CPU使用率已经远远高于正常水平(因为网络调用最终会被缓存),所以这些暂停总是比平时长,甚至超过8秒,如果我正在做在极重的负载下重新启动。终身收集开始没有明显的原因

这里是JVM ARGS:

-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 

我的理解是,终身收藏只能在老年人接近满的时候才会发生;否则会触发它?

回答

1

CMS的一个关键概念是它应该在空间用完之前开始收集,从而允许它同时运行。如果它等到你跑出去,它会触发一个系列停止世界收集。

由于这个原因,有两个阈值来确定何时提前触发集合。

-XX:CMSInitiatingOccupancyFraction=90 (by default) 
-XX+UseCMSInitiatingOccupancyOnly 

如果不设置这些,它会制定出当一个好时机,开始使用“指标”

我的理解是,当老根是应该只出现一个终身集合几乎完整;

这就是Parallel Collector所做的。

+1

感谢您的回复。你是说JVM不知道终身收藏需要多长时间,所以它在第一次的早期不必要地开始?我知道不会等到它实际上已满,但在我的情况下,它几乎没有满。如果是这样的话,那么设置这两个标志是否会迫使JVM在进行第一次终身收集之前等到旧版本已经满了90%? – Cameron 2014-09-29 19:51:50

+0

@Cameron这是它应该做的,是的。我倾向于使伊甸园的面积非常大,例如24 GB,然后任职空间很容易调整;) – 2014-09-29 19:54:57

+0

你把你的伊甸园设置为24GB ......所以你从来没有打过一个完整的GC,因为一切都停留在年轻的gen? – Cameron 2014-09-29 20:16:26

相关问题