OutOfMemoryError異常----Java堆溢出

    在Java虛擬機規範的描述中,除了程序計數器外,虛擬機內存的其他幾個運行時區域都有發生OutOfMemoryError(下面都叫OOM)異常的肯能,下面就通過一些實例來驗證異常發生的場景。
    在下面舉的例子中,在註釋中會設定一些虛擬機的參數,在”VM Args”後邊,如果你是用控制檯命令來執行的程序,直接把這些參數放到Java命令之後就行,如果用的開發工具,Eclipse IDE,才Debug/Run頁籤中設置。

這裏寫圖片描述

    

Java堆溢出


    堆是用來存儲對象實例的,當我們不斷的創建對象,並且保證GC Roots和對象之間有相互的引用關係(GC Roots指垃圾回收器的對象,GC會手機那些不是GC Roots且沒有被GC Roots引用的對象),當對象數量達到最大堆的容量的時候,就會產生內存溢出異常。

/**
 * VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
 * @author Administrator
 *
 */
public class HeapOOM
{

    static class OOMObject{
    }

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

    上述代碼中限制Java堆的大小爲20MB,不可擴展(將堆的最小值-Xms 參數與最大值-Xmx參數設置爲一樣就可以避免堆自動擴展),通過-XX:+HeapDumpOnOutOfMemoryError當虛擬機出現內存溢出的時候Dump出當前的內存堆轉儲快照以便後邊進行分析。運行結果如下:

java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid5504.hprof ...
Heap dump file created [27872304 bytes in 0.150 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:2245)
    at java.util.Arrays.copyOf(Arrays.java:2219)
    at java.util.ArrayList.grow(ArrayList.java:242)
    at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:216)
    at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:208)
    at java.util.ArrayList.add(ArrayList.java:440)
    at test.HeapOOM.main(HeapOOM.java:20)

    刷新項目你就可以看到快照文件,可以用Eclipse Memory Analyzer來打開並進行分析。確定是Memory Leak,還是Memory Overflow。
    處理思路:如果是內存泄漏,通過工具進一步查看泄漏對象到GC Roots的引用鏈,找到泄漏對象是如何和GC Roots相關聯並導致垃圾回收器無法自動回收這些對象的。後邊就可以判斷產生內存溢出的代碼的位置。
    如果不存在內存泄漏問題,檢查虛擬機的堆參數(-Xms -Xmx)跟物理機器對比是否還可以調大,在代碼層面上看看是否存在某些對象生命週期過長、持有狀態時間過長的情況。減少程序運行期間的內存消耗。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章