Java 为什么';JVM不是简单地终止而不是抛出OOME吗?

Java 为什么';JVM不是简单地终止而不是抛出OOME吗?,java,Java,如果非常不鼓励捕获一个OutOfMemoryError,因为捕获错误后您可能不知道JVM的状况,为什么JVM不干脆终止并以某种方式通知用户而不是抛出错误?您有机会转储数据,或者在应用程序未终止时,以其他方式确定OOME的原因 如果未捕获,则终止启动错误的线程。其他线程保持正常运行,当然,除非它们也导致OutOfMemory错误 如果因为怀疑JVM可能处于不一致的状态而想杀死JVM,请将以下内容添加到java选项中: -XX:OnOutOfMemoryError=“kill-9%p”可丢弃文件(异

如果非常不鼓励捕获一个
OutOfMemoryError
,因为捕获错误后您可能不知道JVM的状况,为什么JVM不干脆终止并以某种方式通知用户而不是抛出错误?

您有机会转储数据,或者在应用程序未终止时,以其他方式确定OOME的原因

如果未捕获,则终止启动错误的线程。其他线程保持正常运行,当然,除非它们也导致OutOfMemory错误

如果因为怀疑JVM可能处于不一致的状态而想杀死JVM,请将以下内容添加到java选项中:

-XX:OnOutOfMemoryError=“kill-9%p”
可丢弃文件(异常、错误)是JVM通知用户问题的标准方式。这不是一件抓住它的事情,而是记录发生了什么,在哪里和什么时候。在OOM之后创建一些方法来执行逻辑不是一件确定的事情,因为JVM状态可能不一致,并且通知逻辑可能永远不会执行

此外,作为一个补充操作,您还可以请求OOM错误生成转储,您可以稍后查看(使用转储分析器)并使用


-XX:+HeapDumpOnAutofMemoryError

因为没有单一的标准方法向用户报告错误情况。抛出错误允许在终止之前在顶层捕获对象,并报告可能适当的条件(控制台消息、写入日志文件、显示对话框等)。文档指出,合理的应用程序不应该捕获错误,这是正确的:处理错误的最佳方式是在框架代码中,因为处理错误的方式几乎没有变化(尽管不是零)。具体地说,它们实际上无法从中恢复,这就是为什么大多数应用程序作者试图捕获它们


更新:还有另一个原因。抛出错误不仅允许捕获错误:它还导致执行“finally”块中的代码。由于这些块可能包含关键的清理代码,因此在应用程序终止之前允许它们运行非常重要。

,因为您可以知道该做什么以及如何做

示例:您的代码(尝试)创建一个包含数千万个元素的数组(取决于某些输入)。任何
OutOfMemoryException
都很可能是出于这个原因。特别是,您可以在try/catch块中仅放置阵列创建。异常之后,内存很可能处于相当不错的级别(数组要么完全分配,要么根本没有分配)。您的程序可以继续执行。甚至生成错误消息、发送电子邮件或采取任何其他纠正措施并继续进行下一次输入(来自用户、批次等)


这种劝阻说明通常针对初学者/普通开发人员。试图在程序顶层捕获异常的程序,例如,没有关于触发异常的详细信息。

通过抛出OutOfMemoryError,某个地方可能有足够的内存来接收异常并记录它发生的事实(例如记录器或标准输出)。然后程序可能会退出,而不是试图在可能无效的状态下继续


尽管由于系统内存不足,记录/记录OutOfMemoryError的尝试可能会失败,但它也很有可能成功。如果JVM在OOM上立即退出,则记录问题原因的可能性为零。记录问题的非零概率比记录问题的零概率好。

如果您不知道原因?您如何提供解决方案?即使它通常会终止(即不可恢复),它也可以通过抛出OOM和展开来指定失败的原因(可能还有位置)。您知道,您可以使用选项
-XX:+ExitOnOutOfMemoryError
强制JVM在内存不足错误时退出?好吧,让我们假设您得到了OME,但它不是打印在控制台(或)某个地方,而是JVM悄悄退出,那么您倾向于哪种方式?您的程序退出是因为一切正常(或)内存错误吗?它确实“以某种方式通知用户”,但有一个例外。既然已经存在一种机制,为什么还要设想另一种机制呢?