在Java中处理内存不足情况的最佳方法是什么?

Sim*_*her 11 java linux garbage-collection process out-of-memory

我们有一个应用程序可以生成新的JVM并代表我们的用户执行代码.有时那些内存耗尽,在这种情况下表现得非常不同.有时它们抛出OutOfMemoryError,有时会冻结.我可以通过一个非常轻量级的后台线程来检测后者,该线程在内存不足时停止发送心跳信号.在那种情况下,我们杀死了JVM,但我们永远无法确定未能获得心跳的真正原因是什么.(它也可能是网络问题或分段错误.)

可靠地检测JVM中内存不足情况的最佳方法是什么?

  • 从理论上讲,-XX:OnOutOfMemoryError选项看起来很有希望,但由于这个错误,它实际上无法使用:https://bugs.openjdk.java.net/browse/JDK-8027434

  • 捕获OutOfMemoryError实际上并不是众所周知的理由(例如,你永远不知道它发生在哪里),尽管它在很多情况下都有效.

  • 剩下的情况是JVM冻结并且不会抛出OutOfMemoryError的情况.我仍然确定记忆这个问题的原因.

有没有其他选择或解决方法?垃圾收集设置使JVM自行终止而不是冻结?

编辑:我完全控制了分叉和分叉的JVM以及在这些内部执行的代码,两者都在Linux上运行,如果有帮助,可以使用特定于操作系统的实用程序.

Sim*_*her 1

经过相当长一段时间的实验后,这是对我们有用的解决方案:

  1. 在生成的 JVM 中,捕获OutOfMemoryError并立即退出,用退出代码向控制器 JVM 发出内存不足的信号。
  2. 在生成的 JVM 中,定期检查当前Runtime. 当使用的内存量接近临界值时,创建一个标志文件,向控制器 JVM 发出内存不足情况的信号。如果我们从这种情况中恢复并正常退出,请在退出之前删除该文件。
  3. 控制 JVM 加入派生 JVM 后,它会检查步骤 (1) 中生成的退出代码和步骤 (2) 中生成的标志文件。除此之外,它还会检查文件是否hs_err_pidXXX.log存在以及是否包含“内存不足错误”行。(这个文件是由java生成的,以防崩溃。)

只有在实现所有这些检查之后,我们才能够处理分叉 JVM 内存不足的所有情况。我们相信,从那时起,我们就没有放过一个这样的案例。

java 标志-XX:OnOutOfMemoryError没有被使用是因为 fork 问题,并且-XX:+HeapDumpOnOutOfMemoryError没有被使用是因为堆转储超出了我们的需要。

该解决方案当然不是有史以来编写的最优雅的代码,但为我们完成了工作。