Java堆溢出


Java虛擬機運行數據區

 

 

Java堆用於存儲對象實例,只要不斷地創建對象,並且保證GC Roots到對象之間有可達到路徑來避免垃圾回收機制清除這些對象,那么在對象數量達到最大堆的容量限制后就會產生內存溢出異常。

 

Java堆內存溢出異常測試代碼:

/**
 * VM Args: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
 *
 * -Xms20m:堆的最小值為20MB
 * -Xmx20m:堆的最大值為20MB
 * -XX:+HeapDumpOnOutOfMemoryError 讓虛擬機在出現內存溢出異常時Dump出當前的內存堆轉儲快照
 *  
 */
public class HeapOOM {

    static class OOMObject {    }
    
    public static void main(String[] args) {
        List<OOMObject> list = new ArrayList<>();    
        while(true) {
            list.add(new OOMObject());
        } 
    }
}

運行結果:

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid8660.hprof ...
Heap dump file created [28027169 bytes in 0.111 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
  at java.util.Arrays.copyOf(Arrays.java:3210)
  at java.util.Arrays.copyOf(Arrays.java:3181)
  at java.util.ArrayList.grow(ArrayList.java:261)
  at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:235)
  at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:227)
  at java.util.ArrayList.add(ArrayList.java:458)
  at com.yucong.jvm.HeapOOM.main(HeapOOM.java:25)

 

要解決java heap space這個區域的異常,一般的手段是先通過內存映像分析工具(如:Eclipse Memory Analyzer)對Dump出來的堆轉儲快照進行分析,重點是確認內存中對象是否必要的,也就是要先分清楚到底是出現了內存泄漏(Memory Leak)還是內存溢出(Memory Overflow)。

 

安裝Eclipse Memory Analyzer工具:

點擊菜單:Help的子菜單Eclipse Marketplace,輸入Eclipse Memory Analyzer,搜索結果如下:

 

運行參數配置:

 

運行完后,刷新一下項目,會多出一個hrpof文件:

 

打開此文件,默認第一項Leak Suspects Report,直接Finish:

點擊Details:

以上是處理Java堆內存問題的簡單思路:【來自《深入理解Java虛擬機》】

如果是內存泄漏,可進一步通過工具查看泄漏對象到GC Roots的引用鏈。於是就能找到泄漏對象是通過怎樣的路徑與GC Roots相關聯並導致垃圾收集器無法自動回收它們的。掌握了泄漏對象的類型信息及GC Roots引用鏈的信息,就可以比較准確地定位出泄漏代碼的位置。

如果不存在泄漏,換句話說,就是內存中的對象確實還必須存活着,那就應當檢查虛擬機的堆參數(-Xmx 與 -Xms),與機器物理內存對比看是否可以調大,從代碼上檢查是否存在某些對象生命周期過長、持有狀態時間過長的情況,嘗試減少程序運行期的內存消耗。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM