【开发篇】四、MAT堆内存分析(Memory Analyzer Tool)

文章目录

1、使用

内存溢出后,分析泄露的思路是:

  • 在OOM前,将整个堆内存保存成一个hprof文件
  • MAT打开hprof文件,MAT自行分析可疑对象

添加JVM参数:

java 复制代码
-XX:+HeapDumpOnOutOfMemoryError  //发生OutOfMemoryError错误时,自动生成hprof内存快照文件
-XX:HeapDumpPath=D:\myTmp\heap.hprof  //指定hprof文件的输出路径

模拟个OOM:

2、报错

在MAT里打开hprof文件:

报错

很清晰了,下载JDK17或者换一个低版本的MAT(适配你配置的JDK版本的MAT) ,我当前是JDK11,下载地址【点击】

这里同时配置两个版本的JDK,JDK11我还要用以后:

classpath不变:

JDK版本切到17后,改下mat目录下的MemoryAnalyzer.ini文件,文件内容后面追加以下内容(注意替换目录为自己JDK17的目录,且到bin一层):

java 复制代码
-vm
D:\jdk\jdk-17\bin   

打开MAT:

分析内存泄漏:

大致概览,点击可查看这块是啥:

点击Detail,查看怀疑对象线程的栈信息:

重点看自己代码的栈信息,然后排查这一行写的是否有问题:

3、MAT支配树

在对象引用图中,所有指向对象B的路径都经过对象A,则认为对象A支配对象B。

再看对象D,引用图中想指向对象D,从近处看,可以是对象B,也可以对象C,所以对象B、C对D没有支配关系,往远看,对象A则可以支配对象D。同理,E被C支配,而C被A支配。演化出支配树后:

  • 支配树上对象本身所占空间称浅堆
  • 被对象A支配的所有对象,合起来叫深堆,也叫保留集

A的深堆,就是B、C、D、F、E这些对象加起来的大小,深堆浅堆的概念,表示了一个对象如果可以被回收,能释放多大的内存空间。

java 复制代码
//练习

引用链到支配树:

4、MAT内存泄漏的检测原理

用MAT验证下上面支配树的正确性,改JVM参数,这次不再等内存溢出时才生成内存快照,而是在Full GC后生成:

java 复制代码
//添加JVM参数
-XX:+HeapDumpBeforeFullGC

运行上面练习的代码,并打开生成的快照文件。(卡了一小时没生成,不知道是不是JDK版本太高了,跳过了,反正这个参数也就这里用一下,生产环境狗都不用,卡的我莫名来气,贴个其他示意图)点击选择支配树,找到main线程节点:

这里可以看到每个浅堆的深堆大小。

MAT就是根据支配树,从叶子节点向根节点遍历,如果发现深堆的大小超过整个堆内存的一定比例阈值,就会将其标记成内存泄漏的嫌疑对象、

5、导出运行中系统的内存快照

生产环境观察到堆内存在一直涨,想分析,肯定不能为了导一个快照模拟个OOM,这里导出运行中的快照:

方式一:过JDK自带的jmap命令导出

bash 复制代码
jmap -dump:live,format=b,file=文件路径和文件名 进程ID

参数含义:

java 复制代码
//format=b,即以二进制的形式保存
//-dump:live,只导出标记为存活的对象
//进程ID,自己ps -ef找

方式二:阿尔萨斯的的heapdump

java 复制代码
heapdump --live 文件路径和文件名

上面这个指令可以在tunnel服务端页面执行:

也可以直接启动阿尔萨斯jar包后选择PID,再去执行。MAT打开快照,点击查看对象直方图,里面也显示了一个对象的浅堆和深堆大小,点击表头可排序,这种浅堆和深堆在一个数量级的,一般没问题。


6、补充

MAT在打开当前的堆内存快照时,需要把快照下的堆内存里的所有对象读入到内存中,这对安装MAT的机器配置有要求,一般的开发桌面打不开这么大的快照文件,而且下载一个几十G的hprof文件,下行带宽小也头疼。这时可直接下载系统所在服务器对应操作系统对应的MAT:https://eclipse.dev/mat/downloads.php

java 复制代码
./ParseHeapDump.sh 快照文件路径 org.eclipse.mat.api:suspects org.eclipse.mat.api:overview org.eclipse.mat.api:top_components
//三个参数的含义:
//org.eclipse.mat.api:suspects 生成内存泄漏检测报告
//org.eclipse.mat.api:overview 生成总览图
//org.eclipse.mat.api:top_components 生成组件图

执行脚本,启动MAT,分析堆内存,后生成报告,只需下载包告后解压,查看生成的这几个html报告查看即可。

最后,MAT默认只使用了1G的堆内存,分析超过1G的快照文件,可调大MAT目录下的MemoryAnalyzer.ini这个值:

相关推荐
李慕婉学姐11 小时前
【开题答辩过程】以《基于JAVA的校园即时配送系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·开发语言·数据库
奋进的芋圆13 小时前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin13 小时前
设计模式之桥接模式
java·设计模式·桥接模式
model200513 小时前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉13 小时前
JavaBean相关补充
java·开发语言
提笔忘字的帝国14 小时前
【教程】macOS 如何完全卸载 Java 开发环境
java·开发语言·macos
2501_9418824814 小时前
从灰度发布到流量切分的互联网工程语法控制与多语言实现实践思路随笔分享
java·开发语言
華勳全栈14 小时前
两天开发完成智能体平台
java·spring·go
alonewolf_9914 小时前
Spring MVC重点功能底层源码深度解析
java·spring·mvc
沛沛老爹14 小时前
Java泛型擦除:原理、实践与应对策略
java·开发语言·人工智能·企业开发·发展趋势·技术原理