【Tools】Eclipse MemoryAnalyzer(MAT)工具使用笔记

目录
一、前言
1.1 简介
1.2 下载安装
二、使用
2.1 Histogram(直方图)
2.2 Dominator Tree(支配树)
2.3 Top Consumers
2.4 Duplicate Classes(重复类)
2.5 Suspects(疑似泄露点)
三、问题总结
3.1 分析源码
3.2 解决办法
一、前言
1.1 简介
Eclipse Memory Analyzer 是一个快速且功能丰富的Java 堆分析器,可帮助我们发现内存泄漏并减少内存消耗。简称MAT。

1.2 下载安装
下载地址

下载时需要注意自己的jdk版本,选择对应版本的MAT下载。下载完成,解压。就可以直接打开,免安装。

 

二、使用
双击打开 MemoryAnalyzer.exe
左上角File->Open Heap Dump 选择事先准备好的dump文件(hprof文件)

2.1 Histogram(直方图)
直方图提供了每个类对象的统计


Class Name 表示对象类型
Objects:类的对象的数量。
Shallow Heap:就是对象本身占用内存的大小,不包含对其他对象的引用,也就是对象头加成员变量(不是成员变量的值)的总和。
Retained Heap:是该对象自己的shallow size,加上从该对象能直接或间接访问到对象的shallow size之和。换句话说,retained size是该对象被GC之后所能回收到内存的总和。
我们可以点击Retained Heap让他们按照Retained Heap的大小排序 。从上图可以看出前面的几个对象引用的大部分资源,问题很可能就出现在这些对象上。

2.2 Dominator Tree(支配树)
支配树(Dominator Tree),提供程序中最占内存的对象 。


Class Name 类名
Shallow Heap 浅堆
Retained Heap 深堆
Percentage 百分比
上面的图片可以发现DruidPooledPreparedStatement占用了大部分资源。我们这个时候其实可以直接选择对象右击选择List Objects -> with outgoing references 、 with incoming references 或 Path To GC Roots 看对象的引用链路排查问题。

2.3 Top Consumers
Top Consumers 显示了内存中最大的对象有哪些,他们对应的类是哪些,类加载器classloader是哪些。有些时候,我们在这里就可以看到代码泄露的位置。

 

从上面的图片可以看出来DruidPooledPreparedStatement占用了大部分资源(35.7M)。

2.4 Duplicate Classes(重复类)
Duplicate Classes 检测由多个类加载器加载的类。


2.5 Suspects(疑似泄露点)
提供了MAT诊断的疑似泄露点信息

点击上图的Details信息可以查看详情,如下:

选中一个占用内存较高的对象右击->List objects 然后可以选择with outgoing references 和with incoming references。

with outgoing references 是该对象引用了那些对象实例

with incoming references 是该对象被谁引用

我们还可以进一步查询对象到GC Root的全链路,如图选择去除弱引用

 

疑似泄露点也推断是DruidPooledPreparedStatement造成内存泄露。通过List objects -> with outgoing references 可以看到DruidPooledPreparedStatement的resultSetTrace持有很多的DruidPooledResultSet无法释放。通过with incoming references 可以看到是FilterMap类里面的queryPs占用了很多资源。

三、问题总结
3.1 分析源码
我们找到了代码的FormatMap 发现执行了 DruidPooledPreparedStatement的executeQuery方法。在执行executeQuery方法的时候会把每次查询的结果放到resultSetTrace字段里。因为我们没有清理所有DruidPooledResultSet堆积,导致内存无法回收,最终OOM。

 

3.2 解决办法
DruidPooledPreparedStatement的clearResultSet方法会清理resultSetTrace。但是这个方法是protected的我们不能调用。

最后发现是DruidPooledPreparedStatement的close方法会调用clearResultSet方法清理resultSetTrace。


文章知识点与官方知识档案匹配,可进一步学习相关知识
Java技能树首页概览139126 人正在系统学习中
————————————————
版权声明:本文为CSDN博主「芬达_fenda」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_38538285/article/details/122360793

posted @ 2024-01-17 12:01  GaoYanbing  阅读(158)  评论(0编辑  收藏  举报