【MAT】使用 Eclipse Memory Analyzer 进行堆转储文件分析

环境

java:1.8
Eclipse Memory Analyzer:1.8.0(如果jdk是1.7,请下载相对应的版本)

前言

这篇文章 是篇基础入门篇。
了解下,当然内存发生溢出时,大概一个处理思路;

公司的行情服务器,一直以来都非常吃内存,最近同事反馈说,早上跑job,到了下午
CPU就彪1000%左右;而且内存只剩下1G左右,总内存是64G
使用jstat -gcutil 20845 2000 0来分析,得知,老年代都已经是99.99,而一次FGC的非常长,导致服务器无法正常工作。

所以我们需要知道堆内存中的信息。更确切的说,是哪个类中的哪个变量没有释放内存。

前期准备

我们既然是要分析堆内存的信息;
很明显我们第一步就需要得到一个关于堆内存信息的文件 — 堆转储文件

eclipse

如果是eclipse,则我们可以在Run Configuration中的VM options添加如下配置:

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\heapdump

Tomcat

这段摘抄网上,本人没有实践,因为我公司不使用Tomcat

如果我们部署生产环境,并且使用的是Tomcat容器,则我们需要在bin目录下的catalina.sh文件中,添加下面的配置:

JAVA_OPTS="$JAVA_OPTS -server -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=~/heapdump"

其中,-server 告诉tomcat使用server模式 能获得更大并发数和性能。

java自带的命令 jmap

拿我公司的项目举例,我公司项目使用的是play framework框架;
所以我获取堆转储文件的命令是:

jmap -dump:format=b,file=<dumpfile.hprof> <pid>
//实践 事实上线上环境都可以使用该命令来获取。
jmap -dump:format=b,file=head.bin 3409

构造产生OOM的代码

假设我们自己测试,或者说,你并么有遇到内存泄漏的情况;
我们可以自己来模拟出来;也就是写段程序,让其产生内存泄漏

下面这段代码摘抄之网上,就是在一个web,程序中不断请求,而请求的内容会使其产生大量的对象,并且没有释放。

@Controller
@RequestMapping("/oom")
public class OOMTest {

	private ArrayList<byte[]> memoryLeakArray = new ArrayList<byte[]>();
	private ArrayList<byte[]> anotherArray = new ArrayList<>();
	
	@RequestMapping("test.do")
	public void oomTestAction(HttpServletResponse response) {
        System.out.println("OOM Test~~~~~~~~");
		// 存放小对象的List
		anotherArray.add(new byte[1024]);

		for (int i = 0; i < 1024; i++) {
			byte[] tmp = new byte[1024 * 1024]; // 添加1M的数据到List中
			memoryLeakArray.add(tmp);  //warning: 这里会造成OOM
		}		
	}
}

这里我用了两个ArrayList,其中memoryLeakArray会存放较大的对象,每次请求进来都会往List中放1G的数据,而anotherArray只存放一些较小的对象。启动服务后,在浏览器中访问这个Controller,一般4次之内就能看到JVM抛出OOM异常了。

使用MAT工具分析

安装方法:

1、在eclipse中进行安装:

Help->Eclipse Marketplace
②搜索MAT,安装Eclipse Memory Analyzer,然后重启就可以了。

这里写图片描述

如何选择堆转储文件就可以了。

2、不使用eclipse插件,而是使用其独立的版本:

Memory Analyzer是可以单独使用的:

下载地址:http://www.eclipse.org/mat/downloads.php

这里写图片描述

window版解压后:
这里写图片描述

分析堆转储文件

路径:File --> Open Heap Dump

这里写图片描述

再选择生成的堆转储文件如上面写的heapdump文件,然后就会看到如下一个分析报告图:

这里写图片描述

点击图中的Dominator Tree可以按照对象的大小来展示一个如下的层级结构图,方便我们快速找到那些大对象,它们是最有可能造成内存泄漏的地方:

这里写图片描述

我们再将其展开:

这里写图片描述

我们选择with incoming references,然后我们会在一个新的详情页面看到这个ArrayList属于哪个类,名字叫什么:
这里写图片描述

可以看到,这个正是之前疯狂插入大对象的那个List,找到了这个对象,就可以在代码中查找使用它的地方并定位有问题的代码了。除了通过Overview页面的Dominator Tree查找原因以外,MAT还会生成报告,查找可疑的内存泄漏点。点击Dominator Tree右边的Leak Suspects,可以看到下面这个分析报告,MAT也同样帮我们找到了造成OOM的可疑内存对象:

这里写图片描述

这里写图片描述

至此基本完毕;

下面我贴出,我公司服务器实际生产环境中的情况:

这里写图片描述

这里写图片描述

由于家里看不到公司的代码,这个问题还要等明天去公司里才能确定。

总结

1、使用jmap命令来获取堆转储文件

jmap -dump:format=b,file=<dumpfile.hprof> <pid>

如果只是在本机上测试,则只需要修改的eclipseRun ConfigurationVM options

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\heapdump

如果生成的堆转储文件比较大,则需要先从服务器上下载下来;
再到一台内存足够的本机上,使用mat进行分析


当然也可以下载linux版的MAT,直接到服务器上进行分析:即执行解压包里的脚本即可。
只是服务器上没有图文并茂的说明,所以还是建议下载下来进行分析

2、使用Memory Analyzer进行分析;

如果生成的堆转储文件非常大,比如我公司服务器上生成的就是5.4G大小的文件,
那么就需要调整Memory Analyzer的内存大小;
即找到MemoryAnalyzer.ini文件:

修改-Xmx1024m参数,比如我就是=改为-Xmx6144m

参考地址:
Java OOM 分析Demo

使用 Eclipse Memory Analyzer 进行堆转储文件分析

利用内存分析工具(Memory Analyzer Tool,MAT)分析java项目内存泄露

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山鬼谣me

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值