完整的GC变得非常频繁

时间:2011-10-27 13:40:51

标签: java garbage-collection jvm performance

我在一个tomcat实例上运行了一个Java webapp。在高峰时段,webapp每秒大约30页,通常大约15页。

我的环境是:

O/S: SUSE Linux Enterprise Server 10 (x86_64)
RAM: 16GB

server: Tomcat 6.0.20
JVM: Java HotSpot(TM) 64-Bit Server VM 1.6.0_14
JVM options:
CATALINA_OPTS="-Xms512m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=256m
               -XX:+UseParallelGC
               -Djava.awt.headless=true
               -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps"
JAVA_OPTS="-server"

经过几天的正常运行后,Full GC开始更频繁地发生,并且它成为应用程序可用性的严重问题。在tomcat重新启动之后,问题就会消失,但当然会在5到10天或30天后返回(不一致)。

重启之前和之后的完整GC日志位于http://pastebin.com/raw.php?i=4NtkNXmi

它显示重启前的日志,在6.6天的正常运行时间,因为完整的GC需要2.5秒,并且每隔约6秒发生一次。

然后它会在重新启动后显示一个日志,其中Full GC仅每5-10分钟发生一次。

当Full GCs出现时我使用jmap -dump:format=b,file=dump.hprof PID进行了两次转储(我不确定在发生Full GC时是否完全正确,或者在2个Full GC之间),并在{ {3}}但在泄漏嫌疑人中没有得到任何有用的东西:

  • 60MB:“org.hibernate.impl.SessionFactoryImpl”的1个实例(我使用hibernate和ehcache)
  • 80MB:1,024个“org.apache.tomcat.util.threads.ThreadWithAttributes”实例(这些可能是tomcat的1024个工作者)
  • 45MB:37个“net.sf.ehcache.store.compound.impl.MemoryOnlyStore”实例(这些应该是我在ehcache中的~37个缓存区域)

请注意,我从未收到OutOfMemoryError。

关于我接下来应该去哪看的任何想法?

4 个答案:

答案 0 :(得分:6)

当我们遇到这个问题时,我们最终将其追溯到年轻一代太小。虽然我们给了很多公羊,但年轻一代并没有得到公平的分享。

这意味着小垃圾收集会更频繁地发生,并导致一些年轻的对象被移动到终身代,这意味着更大的垃圾收集。

尝试使用价值相当低的-XX:NewRatio(例如2或3)并查看是否有帮助。

可以找到更多信息here

答案 1 :(得分:4)

我已从-Xmx1024m切换到-Xmx2048m,问题就消失了。我现在有100天的正常运行时间。

答案 2 :(得分:3)

在您的情况下可能发生的事情是,您有很多物品比NewGen生命周期长一点。如果幸存者空间太小,他们会直接前往OldGen。 -XX:+PrintTenuringDistribution可以提供一些见解。你的NewGen足够大,所以请尝试减少SurvivorRatio

另外,jconsole可能会提供更多关于你的记忆发生情况的视觉洞察,试试吧。

答案 3 :(得分:2)

除了调整JVM的各种选项之外,我还建议升级到VM的更新版本,因为后来的版本有更好的调优垃圾收集器(也没有尝试新的实验版)。

除此之外,如果(部分)确定为JVM分配更多内存可能会增加执行GC所需的时间,那么在使用整个16 GB内存和增加内存占用之间存在权衡点,因此您可以尝试双倍所有值,开始

Xms1024m -Xmx2048m -XX:PermSize = 256m -XX:MaxPermSize = 512m

此致

的Massimo