我们有一个应用程序可以生成新的JVM并代表我们的用户执行代码。有时那些内存耗尽,在这种情况下表现得非常不同。有时它们抛出OutOfMemoryError,有时会冻结。我可以通过一个非常轻量级的后台线程来检测后者,该线程在内存不足时停止发送心跳信号。在那种情况下,我们杀死了JVM,但我们永远无法确定未能获得心跳的真正原因是什么。 (它也可能是网络问题或分段错误。)
可靠地检测JVM中内存不足情况的最佳方法是什么?
理论上,-XX:OnOutOfMemoryError选项看起来很有希望,但由于这个错误,它实际上无法使用:https://bugs.openjdk.java.net/browse/JDK-8027434
由于众所周知的原因(例如你永远不知道它发生在哪里)捕获OutOfMemoryError实际上不是一个好的选择,尽管它在许多情况下都有效。
剩下的情况是JVM冻结并且不会抛出OutOfMemoryError的情况。我仍然确定内存 是导致此问题的原因。
有没有替代方法或解决方法?垃圾收集设置使JVM自行终止而不是冻结?
编辑:我完全控制了分叉和分叉的JVM以及在这些内部执行的代码,两者都在Linux上运行,如果使用OS特定的实用程序,则可以使用这有帮助。答案 0 :(得分:2)
唯一真正的选择是(不幸的是)尽快终止JVM。
由于您可能无法更改所有代码以捕获错误并做出响应。如果您不信任OnOutOfMemoryError
(我想知道为什么它不应该使用Java 8使用的vfork,并且它适用于Windows),您至少可以触发堆转储并在外部监视这些文件: / p>
java .... -XX:+HeapDumpOnOutOfMemoryError "-XX:OnOutOfMemoryError=kill %p"
答案 1 :(得分:1)
经过一段时间的实验,这是对我们有用的解决方案:
OutOfMemoryError
并立即退出,通过退出代码向控制器JVM发出内存不足信号。Runtime
的消耗内存量。当使用的内存量接近于临界值时,创建一个标志文件,向控制器JVM发出内存不足情况的信号。如果我们从这个条件中恢复并正常退出,请在退出之前删除该文件。hs_err_pidXXX.log
是否存在并包含“Out of Memory Error”行。 (此文件由java生成,以防它崩溃。)只有在实现所有这些检查之后,我们才能处理分叉JVM内存不足的所有情况。我们相信,从那时起,我们就没有错过这种情况发生的情况。
由于fork问题,未使用java标志-XX:OnOutOfMemoryError
,并且未使用-XX:+HeapDumpOnOutOfMemoryError
,因为堆转储超出了我们的需要。
解决方案肯定不是有史以来最优雅的代码,但是为我们完成了工作。
答案 2 :(得分:0)
如果您对应用程序和配置都有控制权,那么最好的解决方案是查找抛出OutOfMemoryError的根本原因并修复此问题,而不是通过捕获错误或仅重新启动来尝试隐藏症状的JVM。
根据您的描述,它肯定看起来JVM上运行的应用程序正在泄漏内存,只是使用配置不足的资源(在您的情况下为内存)运行,或偶尔处理需要异常大块堆的事务。这些案例的解决方案会有所不同: