JVM OutOfMemory错误“死亡螺旋”(不是内存泄漏)

时间:2010-02-19 16:34:11

标签: java scala jvm solaris out-of-memory

我们最近一直在将许多应用程序从RedHat linux JDK1.6.0_03下运行到Solaris 10u8 JDK1.6.0_16(更高规格的机器),我们注意到了一个相当紧迫的问题:在某些负载下我们的JVM让自己变成了“死亡螺旋”并最终失去记忆。注意事项:

  • 这是不是内存泄漏的情况。这些应用程序运行得很好(在一种情况下超过3年),并且在任何情况下都不确定内存不足错误。有时应用程序有效,有时它们不会
  • 这是而不是我们转移到64位虚拟机 - 我们仍在运行32位
  • 在一个案例中,在1.6.0_18上使用最新的G1垃圾收集器似乎解决了这个问题。在另一个方面,回到1.6.0_03已经有效了
  • 有时我们的应用程序会因HotSpot SIGSEGV错误
  • 而崩溃
  • 这会影响用Java和Scala编写的应用程序

最重要的一点是:行为在那些突然获得大量数据(通常是通过TCP)的应用程序中表现出来。这就好像VM决定继续添加更多数据(可能会将其推进到TG)而不是在“新闻空间”上运行GC,直到它意识到它必须执行完整的GC然后,尽管几乎所有内容都在VM是垃圾,它不知何故决定不收集它!

这听起来很疯狂,但我只是看不出它是什么。你怎么能解释一个应用程序哪一分钟落在最大堆1Gb而下一个工作正常(当应用程序正在做完全相同的事情时,永远不会大约256M)

所以我的问题是:

  1. 还有其他人观察过这种行为吗?
  2. 有没有人建议如何调试JVM本身(而不是我的应用程序)?我如何证明这是一个虚拟机问题?
  3. 是否有任何VM专家论坛,我可以向VM的作者询问(假设他们不在SO上)? (我们没有支持合同)
  4. 如果这是最新版VM中的错误,为什么其他人没有注意到它?

6 个答案:

答案 0 :(得分:2)

我在Solaris机器上遇到了同样的问题,我通过减少 JVM的最大大小来解决它。在执行垃圾收集时,32位Solaris实现显然需要一些开销空间,超出了为JVM分配的空间。因此,例如,使用-Xmx3580M我会收到您描述的错误,但使用-Xmx3072M则会没问题。

答案 1 :(得分:2)

  1. 是的,之前我已经观察过这种行为,通常在经过无数个小时调整JVM参数后,它开始工作。
  2. 垃圾收集,特别是在多线程情况下是不确定的。定义非确定性代码中的错误可能是一个挑战。但是,如果您使用Solaris,则可以尝试使用DTrace,并且有许多JVM选项可用于对等HotSpot。
  3. 继续使用Scala IRC,看看Ismael Juma是否在闲逛(ijuma)。他之前帮助过我,但我认为真正深入的帮助需要付出代价。
  4. 我认为大多数做这种事的人都认为他们要么是JVM调优专家,要么是员工,要么聘请顾问。有些人专门研究JVM。
  5. 为了解决这些问题,我认为您需要能够在受控环境中复制它们,在这种环境中您可以使用不同的调整参数和/或代码更改来精确复制运行。如果你不能做那个招聘,专家可能不会对你有任何好处,而最便宜的解决问题的方法可能就是买更多的RAM。

答案 2 :(得分:2)

有趣的问题。听起来像其中一个垃圾收集器在你的特定情况下效果不佳。

您是否尝试过更改正在使用的垃圾收集器?有很多GC选项,并确定哪些是最佳选择似乎是一种黑色艺术,但我想知道一个基本的改变是否适合你。

我知道有一个“服务器”GC往往比默认的GC工作得更好。你在用它吗?

螺纹GC(我认为是默认设置)可能是您特定情况下最差的,我注意到机器忙时它往往不那么激进。

我注意到的一件事是,通常需要两个GC才能说服Java真正拿走垃圾。我认为第一个倾向于取消链接一堆对象,第二个实际上删除它们。您可能想要做的是偶尔强制两个垃圾收集。这将导致重要的GC暂停,但我从未见过清理整个堆需要两个以上的情况。

答案 3 :(得分:1)

你得到什么样的OutOfMemoryError?堆空间是否耗尽或是与任何其他内存池相关的问题(错误通常会有一条消息提供有关其原因的更多详细信息)。

如果堆耗尽并且可以重现问题(听起来好像可以),我首先要配置VM以在OutOfMemoryErrors上产生堆转储。然后,您可以分析堆并确保它没有填充对象,这些对象仍可通过某些意外引用访问。

当然,您遇到VM错误并非不可能,但如果您的应用程序依赖于1.6.0_03中的实现特定行为,那么在1.6上运行时,它可能由于某种原因或其他原因而成为内存耗尽。 0_16。如果您为应用程序使用某种服务器容器,也可能会发现此类问题。一些开发人员显然无法阅读文档,但往往会观察API行为,并就某些内容的工作原理做出自己的结论。这当然不总是正确的,我遇到了类似的问题,包括Tomcat和JBoss(这两种产品至少只适用于特定的虚拟机)。

答案 4 :(得分:1)

还要确保它不是硬件故障(尝试在服务器上运行MemTest86或类似的。)

答案 5 :(得分:1)

您遇到哪种SIGSEV错误?

如果您运行32位虚拟机,可能就是我在此处描述的内容:http://janvanbesien.blogspot.com/2009/08/mysterious-jvm-crashes-explained.html