mat内存分析
进行一个最简单的实践mat进行内存分析,编写以下代码,改代码将会造成内存溢出
public class Main_work_2_2 {
public static void main(String[] args) {
System.out.println("start out of memory");
List<Thread> threads = new ArrayList<>();
for (int i = 1; i <= 5; i++) {
String threadName = "Thread " + i;
threads.add(new Thread(() -> runByOOM(), threadName));
}
for (Thread thread : threads) {
System.out.println(thread.getName() + "start");
thread.start();
}
}
/**
* run方法运行实例
*/
static void runByOOM() {
// 等待1s让所有线程创建成功,然后开始执行
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Map<String, Object> testMap = new HashMap<>();
int key = 0;
String[] testStringArray = new String[100];
for(int i = 0;i < 100; i++) {
testStringArray[i] = "test";
}
key = 1;
while (key < 1000000) {
// System.out.println(i);
// 此处将发生内存移除
testMap.put(String.valueOf(key), Arrays.copyOf(testStringArray, 100));
key++;
}
}
}
并且配置启动参数如下
-Xms128m JVM启动时分配128M
-Xmx256m JVM运行过程中最大分配内存256M
-XX:+HeapDumpOnOutOfMemoryError 在 OOM 异常出现之后自动生成 dump 文件
运行得到结果如下
可以看出JAVA进程因为内存泄露导致退出,并且自动生成了堆转存文件。
下载独立的MAT,打开并导入刚刚生成的堆转存.hprof文件。
通过饼状图可以看出存在四个问题,分别出现在a、b、c、d上;
查看问题1并点击details查看详情;
先看到累积点的最短路径,可以看到线程:地址是0xf0dabed8 ,名称为Thread 1,其中累积的为一个[java.util.HashMap];
然后再看累积对象所在树的详情,可以看到积累了很多HashMap
然后切换一个视图查看
在第一行输入问题线程名(Thread)进行查询,进入找到累积点(堆占据最大)
可以看到累积了1048592个hashMap<String,OutOfMemoryTest>对象,这就是问题的根源
然后再跟踪堆栈找到问题代码所在位置
此处比较简单,就是一个Thread->run->runByOOM->put
可以看到问题可能是Main_work_2_2的46行,进到对应代码查找,发现确实是预想的将会发生OOM的地方。
这只是一个简单的内存分析实践和例子,之后遇到更加复杂的内存分析和问题分析,还要更加深入的进行学习