垃圾回收太慢会导致OutOfMemoryError吗?

11
在Java中,即使垃圾回收器释放了更多的内存,您是否可能会收到OutOfMemoryError异常,即使应该有足够的内存?换句话说,如果没有足够的内存来分配,那么在抛出OutOfMemoryError之前,gc是否会被强制运行?
谢谢。

不错的问题,但据我所知,除了在代码中将引用标记为null之外,没有办法通过设置任何参数来加速GC。 - kosa
5个回答

6

有一种情况可能导致OOM,既不与堆相关,也不与地址空间相关:当JVM决定GC运行时间过长时。

请参阅这里

换句话说,对于您最初的问题,“如果没有足够的内存分配,会在抛出OutOfMemoryError之前强制运行gc”,答案是肯定的。

(从上面的链接可以看出,gc /运行代码的比率为98%/ 2%,已经非常高了)

(注意2:这适用于Sun / Oracle的JVM,其他实现不清楚)


5

如果GC在释放内存时花费太多时间而不释放大量内存,则可能会出现'java.lang.OutOfMemoryError: GC overhead limit exceeded'错误,详情请参见此问题


2

在OutOfMemoryError抛出之前,GC被强制运行。如果JVM实现了几种类型的GC(如“并发”或“部分”),则在JVM放弃之前会运行“停止世界”GC,因此已尽一切可能避免该错误。

被引用的异常是,如果GC重复运行并仅恢复了微不足道的存储空间(并且堆大小不能进一步扩展),则它将放弃而不是继续以“爬行”模式运行。理论上,对于这种情况,略微增加堆大小将允许“良好”的应用程序正常运行,但正在缓慢消耗堆(这并不罕见)的应用程序将无法从轻微的堆增加中受益,并且稍后也会遇到同样的故障。

[需要注意的是,在GC频繁运行的情况下,如果应用程序表现良好并巧合地运行在堆限制附近,则增加堆大小可能会显着减少GC开销。 (当然,将堆大小增加到大于可用RAM的值通常会使应用程序运行更慢。)]


1

看起来如果你编写的代码适当,就不会遇到OOM。因为JVM会在遇到OOM之前运行垃圾回收。

所以如果你遇到OOM,很可能是你的代码有一些内存泄漏。请检查。

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


1

垃圾回收器通常会在抛出OutOfMemoryError之前尝试找到内存,但是我偶尔看到可以重现的例子,垃圾回收器没有完全跟上进度,调用System.gc()可以避免异常。

但这很少见,通常不应该自己尝试触发垃圾回收。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接