2014-02-08 100 views
3

嘗試捕獲內存異常有多好?我沒有任何經驗來編寫低級別的軟件來管理自己的內存,但我可以想象一種方法來做到這一點。Java嘗試捕獲內存

我不知道Java實際處理內存異常的方式。管理內存的程序是否可能耗盡內存?我什麼時候可以嘗試捕獲內存不足異常,並且無法捕獲異常?

謝謝!

+0

http://stackoverflow.com/questions/1692230/is-it-possible-to-catch-out-of-memory-exception-in-java?rq=1 – NeilA

+0

這絕對是沿着什麼樣的行我問道,但我想知道哪些具體情況容易受到內存不足情況的優雅攻擊。 –

回答

1

嘗試捕捉內存異常有多好?

它在一個層面上工作得很好......但在另一個層面上它可能是有風險的,和/或徒勞的。見下文。

程序管理內存是否可能耗盡內存?

管理內存的「程序」是垃圾回收器。 AFAIK,它總是有足夠的內存用於自己的目的。儘管如果沒有,它將別無選擇,但會導致JVM崩潰。

什麼時候可以嘗試捕獲內存不足異常並且無法捕獲異常?

只有JVM崩潰。或者,如果OOME被拋出到另一個線程堆棧上,而您正試圖捕獲它。


好的,那麼爲什麼要捕捉OOME有風險和/或徒勞。

第一個原因是OOME可以在沒有任何警告的情況下拋出到任何線程堆棧上。當你捕獲異常時,處理程序(通常)無法知道發生了什麼「堆棧」,以及它究竟是如何失敗的。因此,它無法知道應用程序的執行狀態是否已經損壞或被破壞。 (線程是否正在更新重要的東西?是否要通知其他線程...並且線程現在不會收到通知?)

第二個原因是OOME經常是由Java存儲泄露......由於某些事情「掛在」對象上而造成的,當它不應該這樣做時。如果您遇到OOME並嘗試恢復......問題是由於泄漏引起的......有可能有問題的對象仍然可以訪問,而另一個OOME很快就會跟進。換句話說,您的應用程序可能會陷入持續拋出和從OOME中恢復的狀態。最好這會導致性能下降......因爲JVM通常在OOME之前執行的最後一件事是執行完整的(停止世界的)垃圾回收。這需要很長的時間。

請注意,並不是說你永遠不應該抓住OOME。確實,捕捉OOME,報告並關閉通常是一個好策略。

不,有風險/無用的東西是趕上OOME,然後嘗試恢復並繼續運行。

0

在java中內存不是一個例外,它是一個錯誤。你可以在程序層面做任何事情,但這是一個系統限制。您可以通過增加默認堆內存大小來轉義它。

export JVM_ARGS="-Xmx1024m -XX:MaxPermSize=256m" 
2

你不必擔心任何隱含分配中發生的捕捉拋出本身的一部分。它總是可能趕上他們。 JVM甚至可以在遇到問題時保持預先分配的OOM錯誤實例,以便它們自己永遠不會分配失敗。

但是,有可能是次要的擔憂:

  • 任何分配可能是一根稻草壓垮駱駝的背上,這樣你可能不會知道哪裏你的代碼將拋出OOM錯誤。它甚至可能發生在一個完全不同於你正在進行內存消耗的工作的線程中,從而導致JVM的完全不同的部分崩潰。
  • 取決於你要去當你抓住它該怎麼做,你可能會分配更多的內存(如LogRecordStringBuilder,後者甚至可以暗中發生,因爲語法字符串連接的一部分),這可能再次耗盡內存。

這些問題僅適用於內存不足的情況,「正常的方式」,但是,也就是說,通過分配大量的「正常」對象。相反,如果內存不足的操作是例如單個分配,例如10 GB的陣列,那麼它們不會造成問題。

-4


首先,內存不足是java中的錯誤而不是異常。我們只能通過使用try-catch構造或throws子句來處理Java中的異常。

錯誤和異常類都擴展Throwable類。但錯誤是不可恢復的條件和異常是手工。

對於你的情況,通過java中的垃圾收集。

+2

這是不正確的。所有'Throwable'都是可捕獲的,錯誤就是這樣。 – Dolda2000

+0

只有通過約定才能處理異常,只有通過約定才能單獨留下錯誤。你可以抓住(Throwable t)'而只是*不在意*,這將是可怕的。 – Makoto

+0

@ Dolda2000請舉一些例子,否則我不同意你的看法。 – iCodeCademy

0

OutOfMemory是一個錯誤,不是一個例外。錯誤是專門設計用來區分那些可以被程序捕獲並希望恢復到不可恢復的低級錯誤的東西。

如果您認爲可以完成某些操作以從此異常/錯誤中恢復,則只會發現一些問題,您無法從OutOfMemory中恢復。