Ste*_*n C 5

在java中抛出OutOfMemoryError之后是否运行垃圾收集?

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

是否抛出OOME 之后运行取决于应用程序的功能.如果应用程序尝试继续,则GC 通常会在下次应用程序请求更多内存时运行...继续执行.

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


Aaron Digulla说:

因此,在精心设计的应用程序中,您可以捕获并处理OOME,程序将继续存在并继续工作.

这是事实,但由于两个不同的原因,这不是你通常应该做的事情.

第一个原因是在线程尝试分配内存的任何地方都可以抛出OOME .无论JVM当时正在做什么都将被终止......直到OOME被捕获.例如:

  • 如果线程正在更新共享数据结构(在锁定下),那么数据结构将保持半更新.

  • 如果线程是由于通知某个其他线程,那么该通知将永远不会发生,而另一个线程将被卡住等待.

  • 如果线程没有捕获到OOME,那么它将退出,如果没有其他通知,那么您可能会留下一个不再起作用的应用程序.

问题是这些"破损"难以发现或预测,难以从中恢复.

第二个原因是OOME通常表示以下事项之一:

  • 您试图在堆内存不足的情况下执行计算.如果您尝试从OOME恢复,则可能会再次遇到同样的问题.

  • 您的应用程序有内存泄漏; 即,应用程序中的某些数据结构会保留对"垃圾"对象的引用,并阻止它们被回收.如果你试图从OOME恢复,那么任何事情都不会改变,你将再次遇到同样的问题.

因此,成功恢复的先决条件是:

  • 知道 OOME不会破坏重要的JVM中的任何东西,并且
  • 知道你不会再次遇到OOME ......因为根本原因仍然存在.

在大多数应用中,这些是满足......的HARD先决条件.如果它们不符合,那么尝试从OOME恢复的机会很可能会使它处于比退出并重新启动应用程序更糟的状态.