Java中的OutOfMemoryError

xjanting發表於2018-08-24

java.lang.OutOfMemoryError: Java heap space 
原因:Heap記憶體溢位,意味著Young和Old generation的記憶體不夠。 
解決:調整java啟動引數 -Xms -Xmx 來增加Heap記憶體。 

java.lang.OutOfMemoryError: unable to create new native thread 
原因:Stack空間不足以建立額外的執行緒,要麼是建立的執行緒過多,要麼是Stack空間確實小了。 
解決:由於JVM沒有提供引數設定總的stack空間大小,但可以設定單個執行緒棧的大小;而系統的使用者空間一共是3G,除了Text/Data/BSS/MemoryMapping幾個段之外,Heap和Stack空間的總量有限,是此消彼長的。因此遇到這個錯誤,可以通過兩個途徑解決:1.通過-Xss啟動引數減少單個執行緒棧大小,這樣便能開更多執行緒(當然不能太小,太小會出現StackOverflowError);2.通過-Xms -Xmx 兩引數減少Heap大小,將記憶體讓給Stack(前提是保證Heap空間夠用)。 

java.lang.OutOfMemoryError: PermGen space 
原因:Permanent Generation空間不足,不能載入額外的類。 
解決:調整-XX:PermSize= -XX:MaxPermSize= 兩個引數來增大PermGen記憶體。一般情況下,這兩個引數不要手動設定,只要設定-Xmx足夠大即可,JVM會自行選擇合適的PermGen大小。 

java.lang.OutOfMemoryError: Requested array size exceeds VM limit 
原因:這個錯誤比較少見(試著new一個長度1億的陣列看看),同樣是由於Heap空間不足。如果需要new一個如此之大的陣列,程式邏輯多半是不合理的。 
解決:修改程式邏輯吧。或者也可以通過-Xmx來增大堆記憶體。 

在GC花費了大量時間,卻僅回收了少量記憶體時,也會報出OutOfMemoryError,我只遇到過一兩次。當使用-XX:+UseParallelGC或-XX:+UseConcMarkSweepGC收集器時,在上述情況下會報錯,在HotSpot GC Turning文件上有說明: 
The parallel(concurrent) collector will throw an OutOfMemoryError if too much time is being spent in garbage collection: if more than 98% of the total time is spent in garbage collection and less than 2% of the heap is recovered, an OutOfMemoryError will be thrown. 
對這個問題,一是需要進行GC turning,二是需要優化程式邏輯。 

java.lang.StackOverflowError 
原因:這也記憶體溢位錯誤的一種,即執行緒棧的溢位,要麼是方法呼叫層次過多(比如存在無限遞迴呼叫),要麼是執行緒棧太小。 
解決:優化程式設計,減少方法呼叫層次;調整-Xss引數增加執行緒棧大小。

相關文章