2012-11-22 40 views
4

這似乎應該。但是有沒有人肯定或否認?在java中拋出OutOfMemoryError後垃圾收集是否運行?

相關是:

Catching java.lang.OutOfMemoryError?

Is it possible to catch out of memory exception in java?

+0

我希望JVM試圖在投擲OOME之前運行垃圾回收... – poussma

+0

@ ZNK-M看看http://stackoverflow.com/questions/12298725/is-the-garbage-collector-guaranteed-to - 內存不足錯誤 – Yaneeve

+0

@Yaneeve如果您已經看到該問題及其答案,那麼您的問題是什麼? JVM是否嘗試重複錯誤,以查看結果是否不同? –

回答

5

在java中引發OutOfMemoryError後垃圾收集是否運行?

它當然運行之前 OOME拋出。實際上,OOME是,通常是,因爲垃圾回收器發現它無法回收足夠的空間來滿足分配請求。

是否在之後運行OOME被拋出取決於應用程序的功能。如果應用程序嘗試繼續,那麼GC將在通常運行下一次應用程序要求更多內存...在其繼續執行。

1 - 事實上,可以配置GC在檢測到垃圾收集時花費太多時拋出OOME。在這種情況下,JVM可能擁有一定量的未分配內存。


亞倫Digulla這樣說:

因此,在一個精心設計的應用程序,可以捕獲並處理OOME,程序會生存並繼續工作。

這是真的,但它不是你通常應該做的事情,有兩個不同的原因。

第一個原因是OOME可以拋出任何地方線程試圖分配內存。無論JVM當時正在做什麼都將被終止......直到OOME被抓到的地步。例如:

  • 如果線程正在更新共享數據結構(在鎖定下),那麼數據結構將保持半更新。

  • 如果線程是由於通知某個其他線程,那麼該通知將永遠不會發生,另一個線程將被卡住等待。

  • 如果線程沒有捕捉到OOME,那麼它將退出,如果沒有其他通知,那麼您可能會留下一個不再工作的應用程序。

問題是這些「破損」很難檢測或預測,並很難從中恢復。

的第二個原因是,一個OOME是通常指示下列情況之一的:

  • 試圖執行與堆內存不足的運算。如果您嘗試從OOME中恢復,您可能會再次遇到同樣的問題。

  • 你的應用程序有內存泄漏;即應用程序中的某些數據結構會保留對「垃圾」對象的引用,並阻止它們被回收。如果你嘗試從OOME中恢復過來,那麼很可能沒有什麼會改變,並且你會再次遇到同樣的問題。

所以,成功恢復的前提條件是:

  • 知道的OOME不能有損壞,在重要的JVM什麼,
  • 知道你不會再次遇到OOME ......因爲根本原因仍然存在。

在大多數應用中,這些都是符合......的先決條件。如果他們沒有得到滿足,那麼嘗試從OOME中恢復的一個很好的機會會使其處於更差的狀態,比如果您退出並重新啓動應用程序。

0

在OOME的javadoc的,它說:

當Java虛擬機無法分配一個對象,因爲 拋出時,內存不足,並且 垃圾回收器不再提供更多內存。

這意味着它已經運行之前的錯誤。

順便說一句,當你得到這樣的錯誤時,很難恢復,因爲你不能保證有足夠的內存來做其他事情。如果你使用了被卡住的最後一個字節的內存。如果你因爲試圖一次性分配4Gb而出現這個錯誤,那麼你仍然有機會拯救你的靈魂,但是如果你需要這些4Gb來繼續,那麼你再次陷入困境。

http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/OutOfMemoryError.html

4

是。 GC在OutOfMemoryError之前運行,並繼續工作。

OOME是一個像任何其他錯誤:這意味着運行時可能處於有問題的狀態,但不會停止Java。所以當你發現錯誤時,你可以刪除一些引用,錯誤將會消失。

這個問題當然是你不知道其他代碼(例如在另一個線程中)是否可能需要內存,而你試圖找到切割引用,並且代碼可能會拋出另一個OOME並致命地中斷。

因此,在精心設計的應用程序中,您可以捕捉並處理OOME,程序將繼續並繼續工作。

+0

對不起Aaron,@ StephenC的答案比你的更詳細,但你的答案是一樣的好和確實 – Yaneeve

2

如果你的問題確實是否在之後運行OutOfMemoryError:是的。它也運行之前。 OutOfMemoryError不會終止JVM;它拋出而不是對象分配成功,程序繼續。 JVM繼續,包括垃圾收集。

實際上,像Tomcat這樣的一些框架就是爲此設計的。他們分配一些未使用的內存,並且在OutOfMemoryError的情況下釋放它,以便有足夠的空間來完成並有序關閉。這要求GC繼續運行。

+0

這是一個真正困難的選擇,以決定選擇哪個答案,你的或@ AaronDigulla的。他更明確一些。我確實喜歡你的Tomcat例子! – Yaneeve