【问题标题】:java GC periodically enters into several full GC cyclesjava GC周期性地进入几个full GC周期
【发布时间】:2011-01-04 07:40:52
【问题描述】:

环境:

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

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

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

我的 GC 开始正常工作,我看到很多小型 GC,并且一直以来 CPU 显示良好的负载,就像所有 4 个内核都加载到 40-50%,CPU 图表很稳定。

然后,经过 1 分钟的良好工作,CPU 开始在 2 个内核上从 4 个下降到 0%,它的图形变得不稳定,上升和下降(“牙齿”)。我看到,我的线程工作得更慢(我有监控),我看到 GC 在那段时间开始产生大量 FULL GC,接下来的 4-5 分钟这种情况保持不变,然后在短时间内,比如 1 分钟,它会恢复正常情况,但不久之后所有坏事都会重复。

问题: 为什么我的full GC这么频繁??? 如何预防?

我玩 SurvivorRatio - 没有帮助。

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

我的垃圾回收日志:

  1. 开始不错
  2. 然后是长时间的 FULL GC(其中很多)

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]

【问题讨论】:

  • 提示 - 为预格式化代码(例如您的 GC 日志)缩进四个空格。
  • 为什么只有1024M?您是否有机会运行 32 位 JVM?

标签: java multithreading jboss garbage-collection


【解决方案1】:

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

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

您肯定达到了内存限制,即 660160K。此限制是总可用空间,不包括永久代中的空间,即总堆减去幸存者空间之一。 (Ref)

您每四秒创建约 2.2 亿个新的、可 gc 的对象,总内存使用量似乎以 1 MB/秒的速度增加。所以一段时间后,JVM 只会执行 Full GC,直到堆空间用完。

在这种情况下,我强烈怀疑调整内存设置是否会持续很长时间,因为您已经在 6 分钟后达到了限制。

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

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

【讨论】:

  • 我的 gc 输出错误。这是针对较小的内存设置,正确的是关于 Full GC 991231K->648045K(991232K)。我更新了我的问题。我检查了 12 个小时的运行系统,没有 OOM 异常。它设法运行。不管怎么说,还是要谢谢你。我有JProfiler,但还是没有发现问题。
【解决方案2】:

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

另外,有什么理由让你有这些NewSizeMaxNewSizeSurvivorRatio JVM 参数?你有没有观察到这些东西在那里有任何显着的性能提升?在调整任何应用程序时,我的第一种方法是以最小的调整 JVM 运行它,并且仅在我新添加的参数确实 对当前情况产生影响时进行更改。

【讨论】:

  • 你是对的。我只留下了 Xmx 和 Xms,它变得更加稳定。多谢!!!默认帮助。
  • @Peter:很高兴它对你有用。如果这些默认设置最终解决了您的完整 GC 问题,请更新您的原始问题或将此问题标记为已解决。
  • 问题默认解决。但是在我的情况下,默认值是什么?此代码允许获取那些“隐藏”默认值,如果我不提供我的参数stackoverflow.com/questions/1880299/… 我的情况是:NewSize=16777216 MaxNewSize 是 67108864,SurvivorRatio=8。我看到了 GC 的真正改进,更少的 Full GC,但我也将测试负载减少到了我们在生产中的水平,因此在我的案例中,解决方案不仅在 GC 参数方面,而且在降低吞吐量方面。无论使用什么 GC 参数,这个 vm 都无法支持我的初始加载。
  • @Peter:有趣的链接。关于您的问题,就像我之前提到的那样,您的虚拟机很可能实际上需要所有内存,因此无法发挥最佳性能。我个人观察到给虚拟机更多的内存。比通常处理所需的性能更好。您还没有提到您是在运行 32 位还是 64 位 VM(我猜是 32 位)。因为,如果它是 64 位 VM,增加 Xmx 值可能是一个有趣的练习。另外,您还没有依赖我的询问是否可能有多个进程?
  • "你有没有机会产生多个进程?" , 我该怎么做 ?是否有任何可用的 JVM 参数。我有 16 核 CPU,但从未给出任何此类参数。
猜你喜欢
  • 2011-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-16
  • 1970-01-01
  • 1970-01-01
  • 2021-05-23
相关资源
最近更新 更多