捕获OutOfMemoryError

Vir*_*gam 9 java out-of-memory

是否有任何一点java.lang.OutOfMemoryError在Java中捕获内存不足错误()?

Epa*_*aga 11

是的.以下是一些有意义的例子:

  • 如果你想通过优雅地关闭你的程序来处理它
  • 如果要向用户显示问题或记录错误
  • 根据您的设计,您甚至可以清理内存并恢复工作状态

但是,请注意,通常情况下(除非您处于一次分配大量内存的位置),您可能不会特别针对这些情况捕获OutOfMemoryError,而是catch Throwable在您的顶部执行一直主要切入点.

  • 是的,但是你在finally块中执行,而不是在catch块中执行 (4认同)
  • @Sean,这不是一个好主意,因为finally块只会导致一个线程的退出,因为你可以正常关闭,你可能需要保存你的工作并退出程序. (2认同)

Ing*_*ngo 11

黄金法则是只捕获您可以处理的错误.如果您在OutOfMemory错误后可以执行一些有用的操作,那么请继续.


Sea*_*oyd 7

不,赶上ExceptionRuntimeException,但几乎没有(从"从不"改变)Error:

Error是一个子类Throwable ,表示合理的应用程序不应该试图捕获的严重问题.大多数此类错误都是异常情况.的ThreadDeath 错误,虽然是"正常"的情况下,也是一个子类Error,因为大多数应用程序不应该试图抓住它.

注意:
我在这里引用官方的Javadocs.如果你不同意,告诉甲骨文,不要拍信使:-)

  • 请解释原因. (5认同)
  • 不同意"绝不"的原则.:) (2认同)

Ste*_*n C 5

正如其他一些答案所指出的那样,抓住并尝试恢复1是一个坏主意.而不是仅仅重复javadoc说你的异常是不可恢复的,我会试着解释原因.OutOfMemoryErrorError

事实上,至少有两个可靠的理由为什么OOME恢复是不明智的:


第一个原因是OOME 通常是未确诊的内存泄漏的结果.如果您的应用程序捕获并尝试恢复,则泄漏的内存仍然可以访问,因此仍然无法回收.因此,当您的应用程序开始执行操作时,可能会泄漏更多内存...并遇到另一个OOME.应用程序迟早会停止运行.

由于无法确定您的应用程序不会泄漏,因此OOME恢复永远不会是一个可靠,可靠的答案.


第二个原因是当OOME发生时,它可能会对执行状态造成损害.它可能导致线程终止,让其他线程等待永远不会到达的通知等.它可能发生在更新关键应用程序数据结构或(可能更糟)JVM数据结构的过程中.如果您的应用程序然后尝试恢复,它可能会锁定,或者(更糟)它可能会继续使用损坏的数据,并产生不可预测的结果.

除非您对代码库进行取证分析,否则您永远不能完全确定不会发生这种情况.


我不会说你永远不应该试图从OOME中恢复,但总的来说这是一件冒险的事情.而且您的应用程序越复杂,评估风险就越困难.


1 - 我在这里谈论捕获OOME以试图让应用程序像以前一样继续运行; 即恢复申请.捕获OOME以执行(或触发)有序关闭是另一回事.