JVM初体验:内存溢出场景模拟 + Eclipse Memory Analysis的安装和使用
public class Demo {
}
import java.util.ArrayList;
import java.util.List;
/*
* 模拟内存溢出
*/
public class Main {
public static void main(String[] args) {
List<Demo> demoList = new ArrayList<>();
while (true) {
demoList.add(new Demo());
}
}
}
打开任务管理器,在未run之前内存:4.7/7.9GB,run之后不断增多,最后控制台提示:
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.fuya.test1.Main.main(Main.java:13)
如果代码上万行,我们该怎么定位呢?需要一个分析工具
如何利用分析工具进行定位。首先需要把堆内存转储成一个快照,然后通过快照对当前位置进行分析。
如何设置快照:涉及jvm的参数设置
在run as里面的run configuration 里
-XX:+HeapDumpOnOutOfMemoryError -Xms20m -Xmx20m
设置之后呢,就特别快的报堆内存溢出的错了:
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid10376.hprof ...
Heap dump file created [27972658 bytes in 0.175 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.fuya.test1.Main.main(Main.java:13)
与前面不同的是,控制台多了几行代码:将堆转成了快照
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid10376.hprof ...
Heap dump file created [27972658 bytes in 0.175 secs]
放到哪里去了:在代码中,例如在我的
打开,乱码。
要通过专业的分析工具进行查看,用Eclipse Memory Analyzer
下载网址:https://www.eclipse.org/mat/downloads.php
选择合适的版本:我选的是
选择离我们最近的镜像
我选择的是(大连东软信息学院)这个。
下载完毕后,进行解压
双击即可,如下图所示:
1.File --> Open Heap Dump
2.选择刚才生成的文件java_pid10376.hprof后,进行加载
3.点击finish,生成一个摘要信息
可以打开Open Dominator Tree for entire heap进行查看,这个加载一个堆内存树信息,可以看到97.35%,很显然是这里出现了问题。
可以点开查看:
Shallow Heap:表示对象本身所占用的内存大小,不包含它的引用对象
Retained Heap:表示对象本身所占用内存大小+当前直接/间接引用对象所占内存的总和
可以看到:实际上就是我们之前com.fuya.test1.Demo这个类,创建了很多,所导致的内存溢出。这样我们就可以定位到这里
所以:解决内存溢出问题
1.定位问题:找出堆快照,内存分析工具定位问题,
2.制定解决方案:堆内存改大或者增加物理机器的内存或者优化代码或者其他的一些手段