在java中,是否有可能得到一個OutOfMemoryError異常,即使應該有足夠的內存應該垃圾回收釋放更多的內存?換句話說,如果沒有足夠的內存來分配,gc會在拋出OutOfMemoryError之前被強制運行?是否有可能因爲垃圾收集太慢而導致OutOfMemoryError?
謝謝。
在java中,是否有可能得到一個OutOfMemoryError異常,即使應該有足夠的內存應該垃圾回收釋放更多的內存?換句話說,如果沒有足夠的內存來分配,gc會在拋出OutOfMemoryError之前被強制運行?是否有可能因爲垃圾收集太慢而導致OutOfMemoryError?
謝謝。
的GC 將一般儘量拋出OutOfMemoryError
之前找到的內存,但很偶然我見過的重現性例子,其中垃圾收集並不完全跟上,到System.gc()
呼叫阻止例外。
這是非常例外(沒有雙關語意圖),而不是規則雖然 - 你應該幾乎從來沒有試圖挑起你自己的垃圾收集。
有一個這種情況下,您可能會得到一個與堆無關或地址空間相關的OOM:JVM決定GC需要太多時間才能運行。
請參閱here。
換句話說,您的原始問題的答案,即「如果沒有足夠的內存分配,將會在拋出OutOfMemoryError之前強制運行」,這是肯定的。
(你會從以上鍊接查看的比例爲98%/ 2%的GC /運行的代碼,這是已經非常高)
(注2:這是Sun公司/ Oracle的JVM ,不知道其他實現)
如果GC花費太多時間嘗試釋放內存並且沒有釋放大量內存,則可以獲取它'java.lang.OutOfMemoryError:GC overhead overhead exceeded',請參閱this question。
在OutOfMemoryError被拋出之前,GC被強制運行。如果JVM實現了多種GC(比如「併發」或「部分」),那麼GC將在JVM放棄之前運行,因此儘可能避免錯誤。
引用的一個例外是,如果GC重複運行並且只能恢復少量存儲(並且堆大小無法進一步擴展),那麼它會折騰起來而不是繼續以「爬網」模式運行。理論上,對於這種情況,堆大小略微增加可以讓一個「好」的應用程序運行正常,但是一個慢慢啃堆的應用程序(這並不罕見)不會從小堆增加中受益,並且會遇到同樣的失敗只是稍後。
[應當指出的是,在GC運行過於頻繁增加堆大小可顯著減少GC開銷的情況下,如果應用是乖巧,只是巧合發生接近堆限制來運行。 (當然,將堆大小增加到大於可用RAM通常會使應用程序運行得更慢。)]
似乎如果您編寫適當的代碼,您將永遠不會遇到OOM。因爲JVM會在碰到OOM之前運行gc。
所以,如果你打了OOM,它很可能是你的代碼有一些內存泄漏。 選中此項。
有趣的問題,但據我所知是沒有辦法,你可以通過設置任何參數,除了弄髒您的代碼參照空加速比GC。 – kosa 2012-01-03 21:49:20