1, OutOfMemoryError異常 除了程式計數器外,虛擬機記憶體的其他幾個運行時區域都有發生OutOfMemoryError(OOM)異常的可能, java Heap 溢出 一般的異常信息:java.lang.OutOfMemoryError:Java heap spacess java堆用 ...
1, OutOfMemoryError異常
除了程式計數器外,虛擬機記憶體的其他幾個運行時區域都有發生OutOfMemoryError(OOM)異常的可能,
java Heap 溢出
一般的異常信息:java.lang.OutOfMemoryError:Java heap spacess
java堆用於存儲對象實例,我們只要不斷的創建對象,並且保證GC Roots到對象之間有可達路徑來避免垃圾回收機制清除這些對象,就會在對象數量達到最大堆容量限制後產生記憶體溢出異常。
出現這種異常,一般手段是先通過記憶體映像分析工具(如Eclipse Memory Analyzer)對dump出來的堆轉存快照進行分析,重點是確認記憶體中的對象是否是必要的,先分清是因為記憶體泄漏(Memory Leak)還是記憶體溢出(Memory Overflow)。
如果是記憶體泄漏,可進一步通過工具查看泄漏對象到GC Roots的引用鏈。於是就能找到泄漏對象時通過怎樣的路徑與GC Roots相關聯並導致垃圾收集器無法自動回收。
如果不存在泄漏,那就應該檢查虛擬機的參數(-Xmx與-Xms)的設置是否適當。
2, 虛擬機棧和本地方法棧溢出
如果線程請求的棧深度大於虛擬機所允許的最大深度,將拋出StackOverflowError異常。
如果虛擬機在擴展棧時無法申請到足夠的記憶體空間,則拋出OutOfMemoryError異常
這裡需要註意當棧的大小越大可分配的線程數就越少。
3, 運行時常量池溢出
異常信息:java.lang.OutOfMemoryError:PermGen space
如果要向運行時常量池中添加內容,最簡單的做法就是使用String.intern()這個Native方法。該方法的作用是:如果池中已經包含一個等於此String的字元串,則返回代表池中這個字元串的String對象;否則,將此String對象包含的字元串添加到常量池中,並且返回此String對象的引用。由於常量池分配在方法區內,我們可以通過-XX:PermSize和-XX:MaxPermSize限制方法區的大小,從而間接限制其中常量池的容量。
4, 方法區溢出
方法區用於存放Class的相關信息,如類名、訪問修飾符、常量池、欄位描述、方法描述等。
異常信息:java.lang.OutOfMemoryError:PermGen space
方法區溢出也是一種常見的記憶體溢出異常,一個類如果要被垃圾收集器回收,判定條件是很苛刻的。在經常動態生成大量Class的應用中,要特別註意這點。
【情況一】:
Java.lang.OutOfMemoryError: Java heap space:這種是java堆記憶體不夠,一個原因是真不夠,另一個原因是程式中有死迴圈;
如果是java堆記憶體不夠的話,可以通過調整JVM下麵的配置來解決:
< jvm-arg>-Xms3062m < / jvm-arg>
< jvm-arg>-Xmx3062m < / jvm-arg>
【情況二】
java.lang.OutOfMemoryError: GC overhead limit exceeded
【解釋】:JDK6新增錯誤類型,當GC為釋放很小空間占用大量時間時拋出;一般是因為堆太小,導致異常的原因,沒有足夠的記憶體。
【解決方案】:
1、查看系統是否有使用大記憶體的代碼或死迴圈;
2、通過添加JVM配置,來限制使用記憶體:
< jvm-arg>-XX:-UseGCOverheadLimit< /jvm-arg>
【情況三】:
java.lang.OutOfMemoryError: PermGen space:這種是P區記憶體不夠,可通過調整JVM的配置:
< jvm-arg>-XX:MaxPermSize=128m< /jvm-arg>
< jvm-arg>-XXermSize=128m< /jvm-arg>
【註】:
JVM的Perm區主要用於存放Class和Meta信息的,Class在被Loader時就會被放到PermGen space,這個區域成為年老代,GC在主程式運行期間不會對年老區進行清理,預設是64M大小,當程式需要載入的對象比較多時,超過64M就會報這部分記憶體溢出了,需要加大記憶體分配,一般128m足夠。
【情況四】:
java.lang.OutOfMemoryError: Direct buffer memory
調整-XX:MaxDirectMemorySize= 參數,如添加JVM配置:
< jvm-arg>-XX:MaxDirectMemorySize=128m< /jvm-arg>
【情況五】:
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.StackOverflowError
【原因】:這也記憶體溢出錯誤的一種,即線程棧的溢出,要麼是方法調用層次過多(比如存在無限遞歸調用),要麼是線程棧太小。
【解決】:優化程式設計,減少方法調用層次;調整-Xss參數增加線程棧大小。