问题 是否有可能获得OutOfMemoryError,因为垃圾收集太慢了?


在java中,是否有可能出现OutOfMemoryError异常,即使应该有足够的内存,垃圾收集是否会释放更多内存?换句话说,如果没有足够的内存来分配,在抛出OutOfMemoryError之前是否会强制gc运行?

谢谢。


1493
2018-01-03 21:47


起源

不错的问题,但AFAIK没有办法通过设置任何参数来加速GC,除了在代码中标记对null的引用。 - kosa


答案:


 在这种情况下,您可能会获得一个既不与堆相关也不与地址空间相关的OOM:它是在JVM决定GC运行时间过长的时候。

看到 这里

换句话说,原始问题的答案,即“如果没有足够的内存来分配,将在抛出OutOfMemoryError之前强制执行gc”,是的。

(你会从上面的链接看到gc /运行代码的比例是98%/ 2%,这是 非常 已经高了)

(注2:这是针对Sun的/ Oracle的JVM,不知道其他实现)


6
2018-01-03 21:52





你可以得到它,如果GC花费太多时间试图释放内存而不是通过这样做来释放大量内存'java.lang.OutOfMemoryError:超出GC开销限制',请参阅 这个问题


5
2018-01-03 21:53





在抛出OutOfMemoryError之前,GC被强制运行。如果JVM实现了多种GC(例如“并发”或“部分”),那么“停止世界”GC将在JVM放弃之前运行,因此已尽一切努力避免错误。

引用的例外情况是,如果GC重复运行并且只能恢复极少量的存储(并且堆大小无法进一步扩展),那么它将丢弃,而不是继续以“爬行”模式运行。从理论上讲,对于这种情况,稍微增加堆大小将允许“好”应用程序运行正常,但是一个慢慢咀嚼堆的应用程序(这并不罕见)不会从轻微的堆增加中受益,并且会遇到同样的失败只是稍晚一点。

[应该注意的是,在GC运行过于频繁的情况下,增加堆大小可能会显着降低GC开销, 如果 应用程序运行良好,恰巧恰好在堆限制附近运行。 (当然,将堆大小增加到大于可用RAM通常会使应用程序运行得更慢。)]


2
2018-01-03 22:00





似乎如果你编写适当的代码,你永远不会打到OOM。因为JVM会在命中OOM之前运行gc。

因此,如果你点击OOM,很可能你的代码有一些内存泄漏。 检查一下。

http://www.ibm.com/developerworks/library/j-leaks/


1
2018-01-16 08:23





GC  一般以前尝试寻找记忆 OutOfMemoryError 扔了,但是 很偶然 我已经看到了可重现的例子,其中垃圾收集器没有完全跟上,并且调用了 System.gc() 防止异常。

这是非常例外(没有双关语意图)而不是规则 - 你应该差不多 决不 试着自己挑起垃圾收集。


0
2018-01-03 21:51