Java OOM 異常原因及解決方案有哪些?
對于 Java 的運行時數(shù)據(jù)區(qū)域而言,除了程序計數(shù)器外,其他幾個區(qū)域都可能會出現(xiàn) OutOfMemoryError 異常。
堆溢出
通過 -Xms 參數(shù)設(shè)置堆內(nèi)存最小值,-Xmx 設(shè)置堆內(nèi)存最大值,比如 -Xms20m -Xmx20m
解決方案:通過內(nèi)存映像工具(如 Eclipse Memory Analyzer)對 Dump 出來的堆轉(zhuǎn)存快照(使用參數(shù) -XX:+HeapDumpOnOutOfMemoryError 獲?。┻M行分析:
如果溢出原因是內(nèi)存泄漏,則分析如何讓垃圾回收器對其進行回收(通過工具查看對象到 GC Roots 的引用鏈,找到泄露對象的引用路徑,找到具體代碼位置,分析如何寫代碼進行回收)。
如果溢出問題不是內(nèi)存泄漏,也就是內(nèi)存中的對象必須存活,則需要增加堆參數(shù)(-Xms、-Xmx)或者檢查代碼邏輯是否存在問題(如是否存在某些對象生命周期過長、持有狀態(tài)時間過長等)。
虛擬機棧和本地方法棧溢出
通過 -Xss 參數(shù)設(shè)置棧容量,比如 -Xss128k
在單線程條件下,由于 HotSpot 虛擬機不支持棧的動態(tài)擴展(其他的可能支持),使得線程運行時不會因為擴展而出現(xiàn)內(nèi)存溢出的情況,只會因為棧容量無法容納新的棧幀而出現(xiàn) StackOverflowError 異常(棧幀過多 /棧容量太?。?
在多線程條件下,棧內(nèi)存越大,那么能運行的線程越少(因為物理機的內(nèi)存是固定的,且棧是線程私有的),因此在多線程條件下,如果運行大量的線程,也會出現(xiàn) OOM 異常。(但是這樣產(chǎn)生的內(nèi)存溢出異常和??臻g是否足夠并不存在任何直接的關(guān)系,主要取決于操作系統(tǒng)本身的內(nèi)存使用狀態(tài))
方法區(qū)溢出
-XX:MaxMetaspaceSize 用于設(shè)置元空間的最大值。默認(rèn)為-1,即不限制。
-XX:MetaSpaceSize 用于指定元空間的初始空間大小。
-XX:minMetaspaceFreeRation 用于在垃圾收集之后控制最小的元空間剩余容量的百分比,可減少因為元空間不足導(dǎo)致的垃圾收集的頻率。