JVM Tenured/Old Gen 达到限制和服务器挂起

我们的应用程序需要非常大的内存,因为它处理非常大的数据。因此,我们将最大堆大小增加到12GB(-Xmx)。

以下是环境详细信息

OS - Linux 2.6.18-164.11.1.el5    
JBoss - 5.0.0.GA
VM Version - 16.0-b13 Sun JVM
JDK - 1.6.0_18

我们在 QA 和 prod 中具有上述 env 和配置。在QA中,我们将最大PS Old Gen(堆内存)配置为8.67GB,而在Prod中,它只有8GB。

在Prod中,对于特定工作,Old Gen Heap达到8GB,挂在那里并且Web URL变得无法访问。服务器正在关闭。但是在QA中,它也达到了8.67GB,但是执行了完整的GC,并返回到6.5GB或更多。在这里,它不会被绞死。

我们无法为此找到解决方案,因为两个盒子上的环境和配置都是相同的。

我在这里有3个问题,

最大堆的 2/3 将分配给旧代/终身制。如果是这样的话,为什么它在一个地方是8GB,而在另一个地方是8.67GB?

在这种情况下,如何提供新旧和任期的有效比率(12GB)?

为什么它在一个地方是完整的GCed,而不是在另一个地方?

任何帮助都是非常可观的。谢谢。

如果您需要有关环境或conf的更多详细信息,请告诉我。


答案 1

对于您的具体问题:

  1. 新旧代之间的默认比率可能取决于系统以及 JVM 确定的最佳状态。
  2. 使用 指定新旧代之间的特定比率。-XX:NewRatio=3
  3. 如果您的JVM挂起并且堆已满,则可能卡在执行常量GC时。

听起来你需要更多的内存来生产。如果在QA上请求完成,那么也许额外的0.67GB就是它所需要的。不过,这似乎并没有给你留下太多的空间。您是否在 QA 上运行与在 prod 上运行的测试相同?

由于您使用的是 12GB,因此必须使用 64 位。您可以使用该选项节省 64 位寻址的内存开销。它通常节省40%的内存,因此您的12GB将走得更远。-XX:+UseCompressedOops

根据您正在执行的操作,并发收集器也可能更好,特别是为了减少较长的GC暂停时间。我建议尝试这些选项,因为我发现它们运行良好:

-Xmx12g -XX:NewRatio=4 -XX:SurvivorRatio=8 -XX:+UseCompressedOops
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+DisableExplicitGC
-XX:+UseCMSInitiatingOccupancyOnly -XX:+CMSClassUnloadingEnabled
-XX:+CMSScavengeBeforeRemark -XX:CMSInitiatingOccupancyFraction=68

答案 2

你需要获得更多的数据才能知道发生了什么,只有这样你才会知道需要修复什么。在我看来,这意味着

  1. 获取有关垃圾回收器正在做什么的详细信息,这些参数是一个良好的开端(用一些首选路径和文件代替gc.log)

    -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime -Xloggc:gc.log -verbose:gc

  2. 重复运行,扫描gc日志,了解其挂起的时间段,并使用该输出回发

  3. 考虑使用visualgc(需要在服务器上运行jstatd,一个解释如何进行此设置的随机链接是这个),这是jvmstat部分,这是一种v简单的方法来查看堆中各个代的大小(尽管可能不是6小时!

我也强烈建议你也做一些阅读,这样你就知道所有这些开关指的是什么,否则你会盲目地尝试一些东西,而没有真正理解为什么一件事有帮助而另一件事没有。我会从oracle java 6 gc调整页面开始,你可以在这里找到

我只建议在获得基准性能后更改选项。话虽如此,这可能是一个轻松的胜利,你可能要注意它自6u23以来一直默认为on。CompressedOops

最后,您应该考虑升级jvm,6u18正在上升,性能不断提高。

每个作业将需要3个小时才能完成,并且几乎有6个作业一个接一个地运行。运行时的最后一个作业达到最大 8GB 并挂起

这些工作有关系吗?这听起来像是一个渐进的内存泄漏,如果他们不在同一数据集上工作。如果堆使用量不断上升并最终爆炸,那么您就有内存泄漏。你应该考虑 使用 来捕获堆转储(尽管注意,对于13G堆,它将是一个大文件,所以确保你有磁盘空间)如果/当它爆炸。然后,您可以使用jhat来查看当时堆上的内容。-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/some/dir


推荐