我们最近一直在将许多应用程序从RedHat linux JDK1.6.0_03下运行到Solaris 10u8 JDK1.6.0_16(更高规格的机器),我们注意到了一个相当紧迫的问题:在某些负载下我们的JVM让自己变成了“死亡螺旋”并最终失去记忆。注意事项:
SIGSEGV
错误最重要的一点是:行为在那些突然获得大量数据(通常是通过TCP)的应用程序中表现出来。这就好像VM决定继续添加更多数据(可能会将其推进到TG)而不是在“新闻空间”上运行GC,直到它意识到它必须执行完整的GC然后,尽管几乎所有内容都在VM是垃圾,它不知何故决定不收集它!
这听起来很疯狂,但我只是看不出它是什么。你怎么能解释一个应用程序哪一分钟落在最大堆1Gb而下一个工作正常(当应用程序正在做完全相同的事情时,永远不会大约256M)
所以我的问题是:
答案 0 :(得分:2)
我在Solaris机器上遇到了同样的问题,我通过减少 JVM的最大大小来解决它。在执行垃圾收集时,32位Solaris实现显然需要一些开销空间,超出了为JVM分配的空间。因此,例如,使用-Xmx3580M
我会收到您描述的错误,但使用-Xmx3072M
则会没问题。
答案 1 :(得分:2)
为了解决这些问题,我认为您需要能够在受控环境中复制它们,在这种环境中您可以使用不同的调整参数和/或代码更改来精确复制运行。如果你不能做那个招聘,专家可能不会对你有任何好处,而最便宜的解决问题的方法可能就是买更多的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