Java 如何在任何OutOfMemoryException上退出JVM,即使坏人试图抓住它
OOME属于通常不应该从中恢复的错误类别。但是,如果它被隐藏在线程中,或者有人捕获了它,那么应用程序就有可能处于一种状态,即它没有退出,但没有用处。即使在使用可能愚蠢地试图捕捉可丢弃或错误/OOME的库时,关于如何防止这种情况的任何建议?(即您无法直接访问修改源代码)我能想到的唯一一件事是使用AOP将每个方法(注意不要使用java.*)包装为一个try catch for OOME,如果是这样,则记录一些内容并在catch块中调用System.exit()Java 如何在任何OutOfMemoryException上退出JVM,即使坏人试图抓住它,java,jvm,Java,Jvm,OOME属于通常不应该从中恢复的错误类别。但是,如果它被隐藏在线程中,或者有人捕获了它,那么应用程序就有可能处于一种状态,即它没有退出,但没有用处。即使在使用可能愚蠢地试图捕捉可丢弃或错误/OOME的库时,关于如何防止这种情况的任何建议?(即您无法直接访问修改源代码)我能想到的唯一一件事是使用AOP将每个方法(注意不要使用java.*)包装为一个try catch for OOME,如果是这样,则记录一些内容并在catch块中调用System.exit() 这不是一个我称之为优雅的解决方案,但是
这不是一个我称之为优雅的解决方案,但是…如果应用程序JVM中的某段代码决定要尝试捕获OOME并尝试恢复,那么(不幸的是)您无法阻止它。。。除了可能不切实际的AOP英雄之外,AOP英雄肯定对应用程序的性能和可维护性有害。除此之外,您所能做的最好的事情就是使用“onAutofmemoryError”钩子拔掉JVM上的插头。见上面的答案: 基本上,你必须相信其他开发者不会做愚蠢的事情。其他你可能不应该试图防御的愚蠢事情包括:
- 在库方法中调用
deepSystem.exit()
- 调用
和朋友Thread.stop()
- 泄漏开放流、数据库连接等
- 产生大量线程
- 随机挤压(即捕捉并忽略)异常
- 等等
对于那些还不知道这一点的人来说,尝试从OOME中恢复是个坏主意的原因有很多:
从OOME恢复对解决根本原因没有任何作用,这些根本原因通常是内存泄漏、设计不良(即内存浪费)的数据结构和/或启动应用程序时堆太小。在代码和
System.exit()
中捕获OOME如何?我可以想到的另一件事是什么(虽然我不知道如何实现它)将是在某种调试器中运行应用程序。我注意到,当抛出异常时,我的调试器可以停止执行。:-)
因此,可能有人可以实现某种执行环境来实现这一点 您可以使用运行java程序。然而,这假设“坏人”很好地记录了错误:)一种可能性,我很想被谈论掉,就是有一个愚蠢的线程,它的工作就是在堆上做一些事情。如果它接收到OOME,那么它将退出整个JVM 请告诉我这是不明智的 当程序超过设置的堆分配阈值时,可以使用通知 我自己没有使用过它,但是当剩余内存不足时,应该可以通过设置分配阈值并在收到通知时调用System.exit()来关闭它
System.exit()
在其构造函数中java.lang
)中rt.jar
-XX:+ExitOnOutOfMemoryError
to exit on OOME, or to crash:
-XX:+CrashOnOutOfMemoryError
关于老年人:
-XX:OnOutOfMemoryError="<cmd args>; <cmd args>"
用户发布了一条评论,这应该是用户自己的答案。新的JVM特性使这变得简单,特别是
-XX:+ExitOnOutOfMemoryError
要在OOME上退出或崩溃:
-XX:+CrashOnOutOfMemoryError
因为Java 8u92听起来很痛苦;)而且,没有办法区分哪些代码有好的OOME捕捉器,哪些代码有坏的OOME捕捉器。这不会增加太多开销。问题是,如果尝试捕获是在某种模糊方法的中间,你就无能为力了。但是,如果异常发生在库/应用程序的某个较低级别,并且某个较高的方法捕获了它,那么AOP将在这里工作。就像我说的,我想不出还有什么对这个案子有效:)“……你无能为力。”嗯,实际上可能有。。。如果您知道发生这种情况的确切方法,请再次求助于援救:配置切入点以完全转移调用该方法的流程(但大多数情况下这是不可能的,尤其是在需要上下文或使用实例变量的实例方法上)。这确实会很痛苦,但这主要是因为它不是正确的AOP解决方案。您可以编写切入点来拦截捕获块,这意味着您的方面只有t
-XX:+CrashOnOutOfMemoryError