jvm内存模型分析(5)堆内存溢出以及分析
1.模拟堆内存溢出代码
package test;
import java.util.ArrayList;
import java.util.List;
/**
* VM Args:-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
* @author zzm
*/
public class HeapOOM {
static class OOMObject {
}
public static void main(String[] args) {
List<OOMObject> list = new ArrayList<OOMObject>();
while (true) {
list.add(new OOMObject());
}
}
}
2.jvm启动参数设置
目的是因为jvm虚拟机初始的内存还是挺大的,所以缩小堆内存,来快速实现内存溢出。
-Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError

3.程序运行结果:
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid8452.hprof ...
Heap dump file created [27943398 bytes in 0.070 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Unknown Source)
at java.util.Arrays.copyOf(Unknown Source)
at java.util.ArrayList.grow(Unknown Source)
at java.util.ArrayList.ensureExplicitCapacity(Unknown Source)
at java.util.ArrayList.ensureCapacityInternal(Unknown Source)
at java.util.ArrayList.add(Unknown Source)
at test.HeapOOM.main(HeapOOM.java:15)

4.分析:
Java堆用于存储对象实例,只要不断地创建对象,并且保证 GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么在对象数量到达最大堆的容量限制后就会产生内存溢出异常。
代码中限制Java堆的大小为20MB,不可扩展(将堆的最小值-Xms参数与最大值-Xmx参数设置为一样即可避免堆自动扩展),通过参数-XX+Heap DumpOnOutofMemoryError可以让虚拟机在出现内存溢出异常时Dump出当前的内存堆转储快照以便事后进行分析。
程序运行结束以后刷新文件夹会出现一个快照文件

然后利用eclipse memory analyzer内存分析工具,进行分析,定位出现问题的类,和方法,从而找到解决问题的方法



从中我们可以发现,在主线程中,也就是main函数中创建了大量的 OOMObject 对象,并且对象被list集合应用,无法被释放,导致内存溢出。从而定位到问题。