似乎好像应该这样。但是有人可以肯定还是否认呢?

相关的是:

Catching java.lang.OutOfMemoryError?

Is it possible to catch out of memory exception in java?

最佳答案



它肯定会在抛出OOME的之前运行。实际上,由于垃圾收集器发现OOME无法回收足够的空间来满足分配请求1,因此通常会抛出OOME。

是否在OOM引发
之后运行取决于应用程序执行的操作。如果应用程序尝试继续运行,则GC通​​常会在应用程序下次请求更多内存时运行(在其继续执行中)。

1-实际上,可以将GC配置为在检测到花费过多时间进行垃圾回收时抛出OOME。在这种情况下,JVM手中可能会有大量有用的未分配内存。

亚伦·迪古拉(Aaron Digulla)这样说:



的确如此,但是由于两个不同的原因,您通常不应该这样做。

第一个原因是,在线程试图分配内存的任何地方都可能引发OOME。 JVM当时所做的任何事情都将被终止……直至捕获到OOME。例如:

  • 如果线程正在更新共享数据结构(处于锁定状态),则该数据结构将保留一半更新。
  • 如果该线程由于要通知某个其他线程,则该通知将永远不会发生,并且另一个线程将被卡在等待状态。
  • 如果线程未捕获OOME,则它将退出,并且如果没有其他提示,则可能会留下一个不再起作用的应用程序。

  • 问题是这些“破损”很难检测或预测,也很难从中恢复。

    第二个原因是OOME通常表示以下情况之一:
  • 您试图在堆内存不足的情况下执行计算。如果尝试从OOME中恢复,则很可能会再次遇到相同的问题。
  • 您的应用程序内存泄漏;即,您的应用程序中的某些数据结构保留了对“垃圾”对象的引用,并阻止了它们的回收。很有可能,如果您尝试从OOME中恢复,则什么都不会改变,并且一次又一次地遇到相同的问题。

  • 因此,成功恢复的前提是:
  • 知道,OOME不会损坏JVM中重要的任何内容,并且
  • 知道您不会再次遇到OOME了...因为根本原因仍然存在。

  • 这些是在大多数应用中要满足的HARD前提条件。如果不符合要求,则与从退出并重新启动应用程序相比,尝试从OOME中进行恢复很有可能会使其处于更糟的状态。

    10-04 17:43