2012-01-06 69 views
3

This thread,并this pageJVM是否保证在抛出OutOfMemoryError之前运行GC?

它,除非JVM试图完整垃圾回收 第一,包括取消轻声/弱引用对象的[OutOfMemoryError]将永远不会被抛出。

至于这一段代码,

//.. allocate reserved memory 
try { 
    //.. calculation which requires alot of memory even after optimized 
} catch (java.lang.OutOfMemoryError e){ 
    System.gc(); 
    //.. hedge recovery 
} 

是调用System.gc()多余的?

是否已经保证 JVM(根据JVMS)在投掷前已经运行了GC java.lang.OutOfMemoryError

+4

再次:对System.gc()的调用几乎没有必要或实际上有帮助。 – Matthias 2012-01-06 09:42:39

+4

这不是一个答案,所以将它作为评论:你不应该尝试在OOM之后“恢复”。 OOM意味着一些对象无法被创建。不仅在您的应用程序中:也在图书馆中。这意味着,您的应用程序处于严重中断状态 - 无法找出中断的情况。你可以做的最好的是让应用程序死掉,并处理重新启动*外部*。 – alf 2012-01-06 09:43:39

+1

@alf:你确定它会让应用程序处于严重中断状态吗?你不会有“半建”实例或“半装”类,对吗?它应该仍然是“理智的”,或者不像其他类型的例外。 – Thilo 2012-01-06 09:58:12

回答

6

here

时,因为它超出了内存,并且可以通过垃圾收集器提供任何更多的内存,Java虚拟机无法分配一个对象时抛出。

于是,OutOfMemoryException异常之后 GC抛出不能释放更多的内存。

+0

我的意思是这种保证行为,或者这可能会在Java运行时的不同实现之间有所不同? – Pacerier 2012-01-06 09:48:00

+0

我不确定是否有GC需求......但对于给定的JVM,规范说明它必须在OOM之前完成所有工作。 – Thilo 2012-01-06 09:56:32

8

您不应该通过运行System.gc()尝试从OutOfMemoryError中恢复。无论是否严格保证,您都可以在JLS中找到。但是通过并且贯穿 - 这是一个糟糕的主意 - JVM将尽最大努力来满足您的内存分配需求。当它放弃并抛出一个OOM时,游戏就结束了。减少内存使用量或增加堆大小,然后重试。

要更直接地回答你的问题,捕捉OutOfMemoryError确实不是而是表示GC已经运行。例如

try { 
    throw new OutOfMemoryError(); 
} catch (OutOfMemoryError e) { 
    ; 
} 

可能不会调用GC。显然这是一个荒谬的例子。我最近看到的一个更现实的是OOME,其原因是“无法分配新的本地线程”。运行GC可能无法解决这种情况,因为JVM有剩余堆空间,但系统不会允许更多线程。

+0

+1用于“非堆内存”示例 – Thilo 2012-01-06 09:59:27

1

有几种不同类型的OutOfMemoryError。如果我们例如因“无法创建新的本地线程”而得到OOME,那么它不一定是由于GC调用。与“请求的数组大小超过VM限制”一样 - 然后我们将分配大于VM大小的数组,调用GC不是必需的。 JVM试图做到最好,抛出OOME并不意味着它很快就会死亡。由于“超出GC开销限制”而导致的针对OOME的System.gc()调用完全没有意义 - 它会使情况更糟糕。

相关问题