MAT工具定位分析Java堆内存泄漏问题方法

MAT工具定位分析Java堆内存泄漏问题方法

一、引言

生产环境系统发生突然的服务器宕机,两台服务器分别部署了同一套做了负载均衡,但依旧在前后一个小时之差分别宕机,观察其分别产出的log文件得到两个服务器报错的代码位置不一样,还有老年代内存接近上限,该系统的内存分配为最大10G,所以推测应该是某个功能出现内存溢出导致系统宕机。

因为没有在启动命令中加入-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=heapdump.hprof 所以只能在后续重启系统后手动dump下来,建议正式环境的系统启动命令中加入该参数。

二、MAT概述与安装

MAT,全称Memory Analysis Tools,是一款分析Java堆内存的工具,可以快速定位到堆内泄漏问题。该工具提供了两种使用方式,一种是插件版,可以安装到Eclipse使用,另一种是独立版,可以直接解压使用。

我把独立版MAT安装包放到了网盘上,方便直接下载------------

链接:pan.baidu.com/s/10Adz1aqF...

提取码:rkh4

独立版解压后,其内部文件是这样的------

这里有一个MemoryAnalyzer.ini文件,里面有一个Xmx参数,默认是-Xmx1024m,这代表MAT的最大内存大小,根据具体分析的dump文件大小来做适当调整。

点击MemoryAnalyzer.exe,启动完成后,即可以使用它来检查定位内存泄漏相关的问题了。

三、使用MAT分析

我们将这个heapdump.hprof文件导入到MAT里。启动MAT,点击File,选择Open Heap Dump,然后选择对应的hprof文件,在弹框中选择第一个。

Overview主页面显示应用程序内存使用情况的概览,中间的饼图按retained size来显示最大的对象。注意一点是,在MAT中,会有两种大小表示,一个是Retained size,还有一个是Shallow Size,那么,两者有什么区别呢?

  • Shallow Size:表示对象自身占用的内存大小,不包括它引用的对象。
  • Retained size:当前对象内存大小+当前对象直接或间接引用的对象大小,全部的总和,简单理解,就是当前对象被GC后,总共能释放的内存大小。

1.Details显示的是dump文件的情况,表示堆大小为525MB,有22.8k个class,3.5m个Object,2.2k个类加载器等;

2.功能视图模块;

3.报表模块;

我比较喜欢用Actions的Histogram视图和Reports的Leak Suspects报表,Histogram视图是以类为维度来显示其实例数和每个类的使用内存量,可以协助我们查询哪些类对象占用较大内存;Leak Suspects则可以协助分析内存泄漏的原因所在。

- Histogram视图

以Class Name为维度,分别展示各个类的对象数量,Shallow Size,Retained size。默认内存大小是没有显示单位,但用的byte为单位,可以通过Window->Preferences->Memory Analyzer勾选图中的选项,重新打开Histogram视图即可换算成MB、KB等

通过对Retained size倒序排序发现前三位和文件流有关,第四位和tomcat请求有关,怀疑是一个文件处理程序因为请求量上来了,导致内存堆积,最终导致OOM。对第一名右击会有以下选项

使用List Object可以查看对象引用关系,这里查看引用功能,包括本对象引用外部对象with outgoing references与外部对象引用本对象with incoming references。

此处with outgoing references看不出什么,选择with incoming references并按照Retained Heap倒序。

可以发现大多数数组被标记了EExif.MMJFIF,这表明它可能是一个 JPEG 图像文件的开始的标记,所以我们也可以猜测是对图片处理产生了内存堆积,到此基本上可以联想到问题大概率就是最近新上的给上传的图片进行水印处理的功能设计不合理。

- Leak Suspects报表

Leak Suspects报表很直观地展现了一个饼图,图中颜色深的部分表示可能存在内存泄漏的嫌疑。每一个模块都有对应的详情信息。点击See stacktrace得到下面日志信息

可以直观找到对应有问题的代码位置,进一步证明了之前猜测的准确性。

内容来源:

www.cnblogs.com/zhujiqian/p...

相关推荐
炒空心菜菜15 分钟前
MapReduce 实现 WordCount
java·开发语言·ide·后端·spark·eclipse·mapreduce
wowocpp2 小时前
spring boot Controller 和 RestController 的区别
java·spring boot·后端
后青春期的诗go3 小时前
基于Rust语言的Rocket框架和Sqlx库开发WebAPI项目记录(二)
开发语言·后端·rust·rocket框架
freellf3 小时前
go语言学习进阶
后端·学习·golang
全栈派森5 小时前
云存储最佳实践
后端·python·程序人生·flask
CircleMouse5 小时前
基于 RedisTemplate 的分页缓存设计
java·开发语言·后端·spring·缓存
獨枭6 小时前
使用 163 邮箱实现 Spring Boot 邮箱验证码登录
java·spring boot·后端
维基框架6 小时前
Spring Boot 封装 MinIO 工具
java·spring boot·后端
秋野酱6 小时前
基于javaweb的SpringBoot酒店管理系统设计与实现(源码+文档+部署讲解)
java·spring boot·后端
☞无能盖世♛逞何英雄☜6 小时前
Flask框架搭建
后端·python·flask