java GC定期进入几个完整的GC循环

时间:2011-01-04 07:40:53

标签: java multithreading jboss garbage-collection

环境:

sun JDK 1.6.0_16

vm settings:
-XX:+DisableExplicitGC -XX:+UseConcMarkSweepGC -Xms1024 -Xmx1024M -XX:MaxNewSize=448m -XX:NewSize=448m -XX:SurvivorRatio=4(6 also checked) -XX:MaxPermSize=128M

OS: windows server 2003

processor: 4 cores of INTEL XEON 5130,  2000 Hz

我的申请说明: 高强度并发(java 5并发使用)操作每次都通过提交到oracle完成。 它是大约20-30个线程不停地执行任务。

应用程序在JBOSS Web容器中运行。

我的GC开始正常工作,我看到很多小型GC,所有那些时间CPU显示出良好的负载,就像所有4个内核加载到40-50%,CPU图表稳定。

然后,经过1分钟的良好工作后,CPU从2个核心开始从4下降到0%,它的图形变得不稳定,上下移动(“牙齿”)。我看到,我的线程运行速度较慢(我有监控),我看到GC在此期间开始产生大量的FULL GC,接下来的4-5分钟这种情况仍然存在,然后在短时间内,如1分钟它恢复了正常状态,但不久之后,所有坏事都重复了。

问题: 为什么我这么频繁的全GC? 如何防止这种情况?

我和SurvivorRatio一起玩 - 没有帮助。

我注意到,该应用程序运行正常,直到第一个FULL GC发生,而我有足够的内存。然后它运行得很糟糕。

我的GC日志:

  1. 开始很好
  2. 然后是长期的全部GC(其中很多)

  3. 1027.861: [GC 942200K->623526K(991232K), 0.0887588 secs]
    1029.333: [GC 803279K(991232K), 0.0927470 secs]
    1030.551: [GC 967485K->625549K(991232K), 0.0823024 secs]
    1030.634: [GC 625957K(991232K), 0.0763656 secs]
    1033.126: [GC 969613K->632963K(991232K), 0.0850611 secs]
    1033.281: [GC 649899K(991232K), 0.0378358 secs]
    1035.910: [GC 813948K(991232K), 0.3540375 secs]
    1037.994: [GC 967729K->637198K(991232K), 0.0826042 secs]
    1038.435: [GC 710309K(991232K), 0.1370703 secs]
    1039.665: [GC 980494K->972462K(991232K), 0.6398589 secs]
    1040.306: [Full GC 972462K->619643K(991232K), 3.7780597 secs]
    1044.093: [GC 620103K(991232K), 0.0695221 secs]
    1047.870: [Full GC 991231K->626514K(991232K), 3.8732457 secs]
    1053.739: [GC 942140K(991232K), 0.5410483 secs]
    1056.343: [Full GC 991232K->634157K(991232K), 3.9071443 secs]
    1061.257: [GC 786274K(991232K), 0.3106603 secs]
    1065.229: [Full GC 991232K->641617K(991232K), 3.9565638 secs]
    1071.192: [GC 945999K(991232K), 0.5401515 secs]
    1073.793: [Full GC 991231K->648045K(991232K), 3.9627814 secs]
    1079.754: [GC 936641K(991232K), 0.5321197 secs]
    

2 个答案:

答案 0 :(得分:3)

从日志的最后两行开始(在编辑问题之前):

397.245: [Full GC 660160K->443379K(660160K), 2.7433121 secs]
401.793: [Full GC 660160K->446464K(660160K), 2.7697340 secs]

你肯定会达到内存限制,即660160K。此限制是总可用空间,不计算永久生成中的空间,即总堆减去一个幸存者空间。Ref

每创建~220万个新的gc'able对象,总内存使用率似乎以1 MB /秒的速度增加。所以过了一会儿,除了Full GC之外,JVM什么都不会做,直到用尽堆空间。

在这种情况下,我强烈怀疑,调整内存设置将有很长一段时间,因为你已经在6分钟后达到了极限。

看起来你必须查找内存泄漏或存储对大型未使用对象(结果集,DOM对象......)的引用

随着你的新价值观:相同的情况。您仍然会达到相同的内存上限,只是在几分钟后才会出现,因为您分配了更多内存。真的闻起来像是内存泄漏。你仍然以~60 MB / s的速度生成gc'able内容。

答案 1 :(得分:2)

这看起来不像内存泄漏的情况;很可能JVM使用的所有内存都是,这可能解释了频繁的完整GC。你有没有机会产生多个进程?即,而不是具有20-30个线程的单个进程,具有5个进程,每个进程运行4-5个线程?

此外,您是否有任何原因可以使用NewSizeMaxNewSizeSurvivorRatio JVM参数?你有没有通过那些东西观察到任何显着的性能提升?调整任何应用程序时,我的第一种方法是使用最少的调整运行它到JVM,并且只有在我新添加的参数对当前情况产生影响时才进行更改。