除非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?
答案 0 :(得分:8)
您永远不应该尝试通过运行System.gc()从OutOfMemoryError中恢复。无论是否严格保证,您都可以在JLS中找到。但这一直是一个糟糕的主意--JVM将尽最大努力满足你的内存分配需求。当它放弃并抛出一个OOM时,游戏就开始了。要么减少内存使用量,要么增加堆大小,然后重试。
要更直接地回答您的问题,捕获OutOfMemoryError 不意味着GC已运行。例如
try {
throw new OutOfMemoryError();
} catch (OutOfMemoryError e) {
;
}
可能不会调用GC。显然这是一个荒谬的例子。我最近看到的一个更现实的是OOME,原因是“无法分配新的本机线程”。运行GC可能无法解决这种情况,因为JVM有剩余堆空间但系统不允许更多线程。
答案 1 :(得分:6)
答案 2 :(得分:1)
几种不同类型的OutOfMemoryError。例如,如果我们因为"无法创建新的本机线程而获得OOME"那么它不一定是由于GC调用。与"请求的数组大小相同超过VM限制" - 然后我们将分配大于VM大小的数组,不需要调用GC。 JVM正在努力做到这一点并且投掷OOME并不意味着它很快就会死亡。同时为OOME调用System.gc()导致" GC开销限制超出"没有任何意义 - 它会使情况变得更糟。