堆内存溢出

堆内存溢出:
堆内存溢出:java堆内存不够,一个原因是真不够,另一个原因是程序中有死循环;
下面演示的是利用循环的方式在堆中持续建立对象,直到堆内存满溢。
代码:
public class HeapOOM {

public static void main(String[] args) {

    /**
     * maxMemory()为JVM的最大可用内存,可通过-Xmx设置,默认值为物理内存的1/4,设值不能高于计算机物理内存;
     */
    System.out.println("最大可用内存,对应-Xmx(默认物理内存的4分之1):"+
            Runtime.getRuntime().maxMemory()/(1024*1024));

    /**
     * totalMemory()为当前JVM占用的内存总数,其值相当于当前JVM已使用的内存及freeMemory()的总和,
     * 会随着JVM使用内存的增加而增加;
     */
    System.out.println("当前JVM可用空间:"+
            Runtime.getRuntime().freeMemory()/(1024*1024));


    /**
     * freeMemory()为当前JVM空闲内存,因为JVM只有在需要内存时才占用物理内存使用,
     * 所以freeMemory()的值一般情况下都很小,而 JVM实际可用内存并不等于freeMemory(),
     * 而应该等于maxMemory()-totalMemory()+freeMemory()。及其 设置JVM内存分配。
     */
    System.out.println("当前JVM占用的内存总数,相当于已使用的内存加上空闲空间:"+
            Runtime.getRuntime().totalMemory()/(1024*1024));

    List list = new ArrayList<>();

    while (true){
        list.add(new OOMObject());
        System.out.println("最大可用内存,对应-Xmx(默认物理内存的4分之1):"+
                Runtime.getRuntime().maxMemory()/(1024*1024));
        System.out.println("当前JVM可用空间:"+
                Runtime.getRuntime().freeMemory()/(1024*1024));
        System.out.println("当前JVM占用的内存总数,相当于已使用的内存加上空闲空间:"+
                Runtime.getRuntime().totalMemory()/(1024*1024));
    }
}
}

修改调试时的虚拟机参数:


堆内存溢出_第1张图片
image.png
 -Xms:初始堆大小
 -Xmx:最大堆大小
 -XX:+HeapDumpOnOutOfMemoryError :生成堆转储文件

运行main方法,显示结果:

...
最大可用内存,对应-Xmx(默认物理内存的4分之1):5
当前JVM可用空间:0
当前JVM占用的内存总数,相当于已使用的内存加上空闲空间:5
最大可用内存,对应-Xmx(默认物理内存的4分之1):5
当前JVM可用空间:0
当前JVM占用的内存总数,相当于已使用的内存加上空闲空间: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打开堆转储文件java_pid12572.hprof可以看到


堆内存溢出_第2张图片
image.png

空间剩余只有302.2KB
然后查看具体内存消耗情况:


堆内存溢出_第3张图片
image.png

可以看到内存主要消耗在main主线程中,而main主线程中又主要是java.lang.Object对象占用的空间太大,也就是OOMObject对象太多,创建了160065个OOMObject对象,占用了太大的空间。

你可能感兴趣的:(堆内存溢出)