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

一、前言

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。
在这里插入图片描述

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值