堆內(nèi)存溢出

堆內(nèi)存溢出:
堆內(nèi)存溢出:java堆內(nèi)存不夠,一個(gè)原因是真不夠,另一個(gè)原因是程序中有死循環(huán);
下面演示的是利用循環(huán)的方式在堆中持續(xù)建立對象,直到堆內(nèi)存滿溢。
代碼:
public class HeapOOM {

public static void main(String[] args) {

    /**
     * maxMemory()為JVM的最大可用內(nèi)存,可通過-Xmx設(shè)置,默認(rèn)值為物理內(nèi)存的1/4,設(shè)值不能高于計(jì)算機(jī)物理內(nèi)存;
     */
    System.out.println("最大可用內(nèi)存,對應(yīng)-Xmx(默認(rèn)物理內(nèi)存的4分之1):"+
            Runtime.getRuntime().maxMemory()/(1024*1024));

    /**
     * totalMemory()為當(dāng)前JVM占用的內(nèi)存總數(shù),其值相當(dāng)于當(dāng)前JVM已使用的內(nèi)存及freeMemory()的總和,
     * 會隨著JVM使用內(nèi)存的增加而增加;
     */
    System.out.println("當(dāng)前JVM可用空間:"+
            Runtime.getRuntime().freeMemory()/(1024*1024));


    /**
     * freeMemory()為當(dāng)前JVM空閑內(nèi)存,因?yàn)镴VM只有在需要內(nèi)存時(shí)才占用物理內(nèi)存使用,
     * 所以freeMemory()的值一般情況下都很小,而 JVM實(shí)際可用內(nèi)存并不等于freeMemory(),
     * 而應(yīng)該等于maxMemory()-totalMemory()+freeMemory()。及其 設(shè)置JVM內(nèi)存分配。
     */
    System.out.println("當(dāng)前JVM占用的內(nèi)存總數(shù),相當(dāng)于已使用的內(nèi)存加上空閑空間:"+
            Runtime.getRuntime().totalMemory()/(1024*1024));

    List<OOMObject> list = new ArrayList<>();

    while (true){
        list.add(new OOMObject());
        System.out.println("最大可用內(nèi)存,對應(yīng)-Xmx(默認(rèn)物理內(nèi)存的4分之1):"+
                Runtime.getRuntime().maxMemory()/(1024*1024));
        System.out.println("當(dāng)前JVM可用空間:"+
                Runtime.getRuntime().freeMemory()/(1024*1024));
        System.out.println("當(dāng)前JVM占用的內(nèi)存總數(shù),相當(dāng)于已使用的內(nèi)存加上空閑空間:"+
                Runtime.getRuntime().totalMemory()/(1024*1024));
    }
}
}

修改調(diào)試時(shí)的虛擬機(jī)參數(shù):


image.png
 -Xms:初始堆大小
 -Xmx:最大堆大小
 -XX:+HeapDumpOnOutOfMemoryError :生成堆轉(zhuǎn)儲文件

運(yùn)行main方法,顯示結(jié)果:

...
最大可用內(nèi)存,對應(yīng)-Xmx(默認(rèn)物理內(nèi)存的4分之1):5
當(dāng)前JVM可用空間:0
當(dāng)前JVM占用的內(nèi)存總數(shù),相當(dāng)于已使用的內(nèi)存加上空閑空間:5
最大可用內(nèi)存,對應(yīng)-Xmx(默認(rèn)物理內(nèi)存的4分之1):5
當(dāng)前JVM可用空間:0
當(dāng)前JVM占用的內(nèi)存總數(shù),相當(dāng)于已使用的內(nèi)存加上空閑空間:5
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid12572.hprof ...
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.example.outofmemoryerror.HeapOOM.main(HeapOOM.java:40)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Heap dump file created [10636779 bytes in 0.052 secs]

利用MemoryAnalyzer打開堆轉(zhuǎn)儲文件java_pid12572.hprof可以看到


image.png

空間剩余只有302.2KB
然后查看具體內(nèi)存消耗情況:


image.png

可以看到內(nèi)存主要消耗在main主線程中,而main主線程中又主要是java.lang.Object對象占用的空間太大,也就是OOMObject對象太多,創(chuàng)建了160065個(gè)OOMObject對象,占用了太大的空間。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容