JVM是否可以保证在抛出OutOfMemoryError之前运行GC?

时间:2012-01-06 09:35:11

标签: java garbage-collection jvm

This threadthis page

  

除非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)在投掷java.lang.OutOfMemoryError之前运行了GC?

3 个答案:

答案 0 :(得分:8)

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

要更直接地回答您的问题,捕获OutOfMemoryError 意味着GC已运行。例如

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

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

答案 1 :(得分:6)

来自here

  

当Java虚拟机因内存不足而无法分配对象时抛出,垃圾收集器不再提供更多内存。

因此,在 GC无法释放更多内存之后,抛出OutOfMemoryException

答案 2 :(得分:1)

几种不同类型的OutOfMemoryError。例如,如果我们因为"无法创建新的本机线程而获得OOME"那么它不一定是由于GC调用。与"请求的数组大小相同超过VM限制" - 然后我们将分配大于VM大小的数组,不需要调用GC。 JVM正在努力做到这一点并且投掷OOME并不意味着它很快就会死亡。同时为OOME调用System.gc()导致" GC开销限制超出"没有任何意义 - 它会使情况变得更糟。