3 回答

TA貢獻(xiàn)1895條經(jīng)驗 獲得超3個贊
它可能有效,但是通常是一個壞主意。無法保證您的應(yīng)用程序?qū)⒊晒謴?fù),或者無法知道它是否成功。例如:
即使采取恢復(fù)步驟(例如釋放保留的內(nèi)存塊)后,實(shí)際上可能沒有足夠的內(nèi)存來執(zhí)行請求的任務(wù)。在這種情況下,您的應(yīng)用程序可能陷入一個循環(huán),在該循環(huán)中,它似乎反復(fù)出現(xiàn)恢復(fù),然后再次耗盡內(nèi)存。
OOME可以在任何線程上拋出。如果應(yīng)用程序線程或庫未設(shè)計為應(yīng)對該問題,則可能會使某些長期存在的數(shù)據(jù)結(jié)構(gòu)處于不完整或不一致的狀態(tài)。
如果線程由于OOME而死,則作為OOME恢復(fù)的一部分,應(yīng)用程序可能需要重新啟動它們。至少,這會使應(yīng)用程序更加復(fù)雜。
假設(shè)一個線程使用通知/等待或更高級別的機(jī)制與其他線程同步。如果該線程從OOME中消失,則可能會留下其他線程來等待通知(etc),這些通知永遠(yuǎn)不會出現(xiàn)...例如。為此進(jìn)行設(shè)計可能會使應(yīng)用程序更加復(fù)雜。
總而言之,設(shè)計,實(shí)施和測試要從OOME中恢復(fù)的應(yīng)用程序可能會很困難,尤其是在應(yīng)用程序(或其運(yùn)行所在的框架或所使用的任何庫)是多線程的情況下。將OOME視為致命錯誤是一個更好的主意。
另請參閱我對相關(guān)問題的回答:
編輯 -針對此后續(xù)問題:
換句話說,如果將OOME拋出到應(yīng)用程序服務(wù)器(jboss / websphere / ..)中,我是否必須重新啟動它?
不,你不必須重新啟動。但這可能是明智的選擇,尤其是如果您沒有良好/自動的方法來檢查服務(wù)是否正常運(yùn)行時。
JVM將恢復(fù)正常。但是,應(yīng)用程序服務(wù)器和應(yīng)用程序本身可能會恢復(fù),也可能無法恢復(fù),這取決于它們?yōu)閼?yīng)對這種情況而設(shè)計的程度。(我的經(jīng)驗是,某些應(yīng)用程序服務(wù)器并非旨在解決此問題,并且設(shè)計和實(shí)施復(fù)雜的應(yīng)用程序以從OOME中恢復(fù)非常困難,而正確地對其進(jìn)行測試則更加困難。)
編輯2
針對此評論:
“其他線程可能會等待通知(等)永遠(yuǎn)不會到來”真的嗎?被殺死的線程是否不會解開其堆棧,隨即釋放資源,包括持有的鎖?
對真的!考慮一下:
線程#1運(yùn)行此命令:
synchronized(lock) {
while (!someCondition) {
lock.wait();
}
}
// ...
線程#2運(yùn)行此命令:
synchronized(lock) {
// do stuff
lock.notify();
}
如果線程#1正在等待通知,并且線程#2在該// do something節(jié)中獲得OOME ,則線程#2將不會進(jìn)行notify()調(diào)用,線程#1可能會永遠(yuǎn)卡住,等待永遠(yuǎn)不會發(fā)生的通知。當(dāng)然,保證線程#2釋放lock對象上的互斥體...但這還不夠!
如果不是,線程運(yùn)行的代碼不是異常安全的,這是一個更普遍的問題。
我聽說過“異常安全”這個詞(盡管我知道您的意思)。Java程序通常沒有設(shè)計為可應(yīng)對意外異常。確實(shí),在上述情況下,使應(yīng)用程序異常安全可能很困難,甚至不可能。
您需要某種機(jī)制將線程#1的故障(由于OOME)變成對線程#2的線程間通信失敗通知。Erlang可以做到這一點(diǎn)……但是Java卻沒有。他們之所以能夠在Erlang中做到這一點(diǎn),是因為Erlang進(jìn)程使用嚴(yán)格的類似于CSP的原語進(jìn)行通信。即沒有共享的數(shù)據(jù)結(jié)構(gòu)!

TA貢獻(xiàn)2041條經(jīng)驗 獲得超4個贊
我會說這部分取決于導(dǎo)致OutOfMemoryError的原因。如果JVM的內(nèi)存確實(shí)不足,最好重新啟動它,并在可能的情況下使用更多的內(nèi)存(或效率更高的應(yīng)用程序)。但是,我已經(jīng)看到大量OOME是由分配2GB數(shù)組等引起的。在那種情況下,如果它像是J2EE Web應(yīng)用程序,則錯誤的影響應(yīng)該限制在該特定應(yīng)用程序上,并且在JVM范圍內(nèi)重新啟動不會有任何好處。
添加回答
舉報