2012-01-03 42 views
11

在java中,是否有可能得到一個OutOfMemoryError異常,即使應該有足夠的內存應該垃圾回收釋放更多的內存?換句話說,如果沒有足夠的內存來分配,gc會在拋出OutOfMemoryError之前被強制運行?是否有可能因爲垃圾收集太慢而導致OutOfMemoryError?

謝謝。

+0

有趣的問題,但據我所知是沒有辦法,你可以通過設置任何參數,除了弄髒您的代碼參照空加速比GC。 – kosa 2012-01-03 21:49:20

回答

0

的GC 一般儘量拋出OutOfMemoryError之前找到的內存,但很偶然我見過的重現性例子,其中垃圾收集並不完全跟上,到System.gc()呼叫阻止例外。

這是非常例外(沒有雙關語意圖),而不是規則雖然 - 你應該幾乎從來沒有試圖挑起你自己的垃圾收集。

6

一個這種情況下,您可能會得到一個與堆無關或地址空間相關的OOM:JVM決定GC需要太多時間才能運行。

請參閱here

換句話說,您的原始問題的答案,即「如果沒有足夠的內存分配,將會在拋出OutOfMemoryError之前強制運行」,這是肯定的。

(你會從以上鍊接查看的比例爲98%/ 2%的GC /運行的代碼,這是已經非常高)

(注2:這是Sun公司/ Oracle的JVM ,不知道其他實現)

5

如果GC花費太多時間嘗試釋放內存並且沒有釋放大量內存,則可以獲取它'java.lang.OutOfMemoryError:GC overhead overhead exceeded',請參閱this question

2

在OutOfMemoryError被拋出之前,GC被強制運行。如果JVM實現了多種GC(比如「併發」或「部分」),那麼GC將在JVM放棄之前運行,因此儘可能避免錯誤。

引用的一個例外是,如果GC重複運行並且只能恢復少量存儲(並且堆大小無法進一步擴展),那麼它會折騰起來而不是繼續以「爬網」模式運行。理論上,對於這種情況,堆大小略微增加可以讓一個「好」的應用程序運行正常,但是一個慢慢啃堆的應用程序(這並不罕見)不會從小堆增加中受益,並且會遇到同樣的失敗只是稍後。

[應當指出的是,在GC運行過於頻繁增加堆大小可顯著減少GC開銷的情況下,如果應用是乖巧,只是巧合發生接近堆限制來運行。 (當然,將堆大小增加到大於可用RAM通常會使應用程序運行得更慢。)]