利用 MAT 排查堆溢出

举报
SHQ5785 发表于 2024/06/25 10:01:36 2024/06/25
【摘要】 一、前言在前期博文中,堆已经讲得差不多啦,这章我们以一个例子来说说如何设置以及当发生堆溢出的时候怎么排查问题。先看一小段代码:public class Test { private static List<Test> list = new ArrayList<Test>(); private static void main(String[] args) { while(true){ ...

一、前言

在前期博文中,堆已经讲得差不多啦,这章我们以一个例子来说说如何设置以及当发生堆溢出的时候怎么排查问题。先看一小段代码:

public class Test {
	private static List<Test> list = new ArrayList<Test>();
	private static void main(String[] args) {
		while(true){
			Test test = new Test();
			list.add(test);
		}
	}
}

二、参数设置

上面的代码中使用了一个无限循环来为list添加对象,如果采用默认的堆大小的话可能要等待好久才能出现堆溢出的错误,因此我们要将其设置小一点:
-Xms10m -Xmx10m -XX:+HeapDumpOnOutOfMemoryErrorelipse中的设置方法我们在前期博文《JVM进阶(一):初识 JAVA 栈》讲过了,这里不多说啦。-Xms10m,意思就是堆的最小内存为10m。同理-Xmx10m的意思就是最大内存也为10m。这两个都是设置为10m,那么堆的大小就是10m。而-XX:+HeapDumpOnOutOfMemoryError指的是当发生内存溢出的时候会将当前的内存使用情况生成一个快照保存起来,但需要eclipse下载一个MAT插件,下载方式自行百度。

三、问题排查

使用刚刚设置的参数启动程序,稍等一小会就会出现以下错误:

显示出堆溢出错误,并且生成了一个叫做java_pid4792.hprof的文件,我们刷新项目便可以看到该文件,双击打开,需要一段的加载时间。

首先可以看到的是一个饼状图,占用部分最大的便是发生溢出错误的部分,我们接着往下看 :

我们这里看看画红线的部分,这里列出一些存活的大对象,在溢出的时候一般先怀疑大对象,我们点进去:

这里列出占用内存最大的几个对象,很显然,第一个很可疑,占用率达到了94.64%!继续跟进:

发现都是test对象,因此排查的时候可以从这个方面下手。接着我们右键该对象选择Path To GC Root(在引用链上的路径),再选择exclue all phantom/weak/soft etc. reference ,结果如图:

可以看到是被List引用了,因此一直在引用链上,导致无法被回收掉,也就出现了内存溢出。
本文只讲了MAT的一个最基本的用途,指出排查思路,感兴趣的小伙伴可以结合工作上的案例自己深入的去了解其更多的用途。

四、拓展阅读

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。