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

时间:2012-11-22 08:42:42

标签: java error-handling garbage-collection

看起来好像应该这样。但有人可以肯定或否认吗?

相关的是:

Catching java.lang.OutOfMemoryError?

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

4 个答案:

答案 0 :(得分:5)

  

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

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

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

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


Aaron Digulla说:

  

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

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

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

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

  • 如果线程是由于通知某个其他线程,则该通知将永远不会发生,而另一个线程将等待等待。

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

问题是这些“破损”难以发现或预测,难以从中恢复。

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

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

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

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

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

这些是在大多数应用中满足......的硬条件。如果他们没有得到满足,那么尝试从OOME恢复将很有可能使其处于更糟糕的状态,而不是退出并重新启动应用程序。

答案 1 :(得分:4)

是。 GC在OutOfMemoryError之前运行,并继续工作。

OOME与其他任何错误一样:它意味着运行时可能处于有问题的状态,但这并不能阻止Java。因此,当您捕获错误时,您可以删除一些引用,错误将消失。

问题当然是你无法知道其他代码(例如在另一个线程中)是否可能需要内存,而你试图找到cut的引用,并且该代码可能会抛出另一个OOME并致命地破坏。

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

答案 2 :(得分:2)

如果你的问题确实是在 OutOfMemoryError后运行:是的。它之前也运行过。 OutOfMemoryError不会终止JVM;它抛出而不是对象分配成功,程序继续。 JVM继续,包括垃圾收集。

事实上,像Tomcat这样的一些框架就是为此而设计的。它们分配了一些未使用的内存,如果是OutOfMemoryError,则释放它,以便有足够的空间来完成并有序关闭。这要求GC继续运行。

答案 3 :(得分:0)

在OOME的javadoc中,它说:

  

当Java虚拟机无法分配对象时抛出,因为   内存不足,没有更多的内存可供使用   垃圾收集器。

这意味着它已经运行错误。

顺便说一句,当你遇到这样的错误时,很难恢复,因为你不能保证有足够的内存来做其他事情。如果你使用了记忆的最后一个字节,你就会陷入困境。如果你有这个错误,因为你试图一次性分配4Gb,那么你仍然有机会拯救你的灵魂,但如果你需要那些4Gb继续,那么你再次陷入困境。

http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/OutOfMemoryError.html