问题 为什么JVM不会简单地终止而不是抛出OOME?


如果赶上 OutOfMemoryError 非常气馁,因为你在捕获错误后可能不知道JVM的状况,为什么JVM不会简单地终止并以某种方式通知用户而不是抛出错误?


2867
2017-08-30 20:00


起源

如果你没有原因?你怎么能提供解决方案? - kosa
即使它通常终止(即不被认为是可恢复的),它也能够通过抛出OOM和展开来指定失败的原因(也许是位置)。 - user2246674
你知道吗,你可以使用这个选项 -XX:+ExitOnOutOfMemoryError 强制JVM退出内存不足错误? - nosid
好吧,让我们说你得到了OME,但它没有打印在控制台(或)某些地方,但JVM悄然退出,那么你倾向于哪个方向?你的程序退出是因为一切都很好(或)outofmemoryerror? - kosa
除了例外,它确实“以某种方式通知用户”。为什么在已经存在的情况下想出另一种机制? - user207421


答案:


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

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


5
2017-08-30 20:21





因为你可以知道该做什么以及如何做。

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

这种沮丧的笔记通常针对初学者/普通开发者。会尝试在程序的顶层捕获异常,例如,没有关于触发它的内容的详细信息。


4
2017-08-30 20:30





Throwables(异常,错误)是JVM通知用户有关问题的标准方法。它不是捕获它的东西,而是记录发生的事情,地点和时间。在OOM之后创建一些执行逻辑的方法并不确定,因为JVM状态可能不一致,并且通知逻辑可能永远不会被执行。

此外,作为一个补充操作,您还可以请求OOM错误生成转储,您可以稍后查看(使用转储分析器)并在应用程序中搜索内存泄漏,使用

-XX:+HeapDumpOnOutOfMemoryError


1
2017-08-30 20:10



例外!=错误 - Philipp Sander
是的,修好..谢谢 - Cristian Meneses


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

如果它未被捕获,它将终止发起错误的THREAD。其他线程保持正常运行,除非它们当然也会导致OutOfMemoryErrors。

如果你想要杀死你的JVM,不管是什么因为你怀疑它可能处于不一致状态,请将它添加到你的java选项:

-XX:OnOutOfMemoryError="kill -9 %p"


1
2017-08-30 20:05





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

虽然这种记录/记录OutOfMemoryError的尝试可能会失败,因为系统内存不足,但它很可能会成功。如果JVM在OOM上即时退出,则记录问题的可能性为零。记录问题的非零机会优于记录问题的零机会。


0
2017-08-30 20:44