eclipse占用内存过大_Java性能调优学习(三)-jmap+mat分析内存溢出问题实战

6dfdc3eb37336acecbb8e279a6c998a7.png

上一节我们讲了jinfo,jstat,jmap的使用,还简单的讲了下如何使用jmap导出内存映像文件,这次,我们来实战一把内存溢出问题。

环境准备

首先我们先模拟一下内存溢出的场景,以下这段代码在访问后肯定会造成堆内存溢出,代码如下:

@RestController@RequestMapping("/section1")public class TestHeapController { private List heapList = new ArrayList<>(); /*** * -Xms16m -Xmx32m */ @GetMapping("/heap") public ResultVO testHeap() { int i = 0; while (true) { Student student = new Student(i++, UUID.randomUUID().toString()); System.out.println(student.toString()); heapList.add(student); } }}

那么我们如何解决这样的问题,在生产环境中,代码肯定不会这么清晰简单,那么我们怎么去分析和解决呢?我们需要导出内存映像文件来分析解决。

有两种方式可以导出内存映像文件,这边我们在重温一下。

有两种方式可以导出映像文件:

1. 配置参数内存溢出自动导出

-XX:+HeapDumpOnOutOfMemoryError-XX:HeapDumpPath=./

2. 使用jmap命令手动导出

关于jmap如何导出,可以看我的上一篇文章,Java性能调优学习(二)-jinfo,jstat,jmap的使用

下面我们先准备一下需要分析的内存映像文件,配置JVM参数后,启动我们刚刚的实例代码,开多个浏览器多次访问后,很快就会出现异常,这个时候由于配置了参数,会自动导出内存映像文件,我们将这个文件先放好,备用。

5b4c1896a8eb9867431fe4bdd8ab0886.png

参数配置

448b07d5bb70941c777ab0f9661e347a.png

自动导出

下面就轮到我们的内存分析工具MAT登场啦。

MAT

MAT(MemoryAnalyzerTool)工具是eclipse的一个插件(MAT也可以单独使用),使用起来非常方便,尤其是在分析大内存的dump文件时,可以非常直观的看到各个对象在堆空间中所占用的内存大小、类实例数量、对象引用关系、利用OQL对象查询,以及可以很方便的找出对象GCRoots的相关信息,当然最吸引人的还是能够快速为开发人员生成内存泄露报表,方便定位问题和分析问题。

MAT工具的下载地址为:https://www.eclipse.org/mat/downloads.php

下载完成后,直接解压,运行其中的MemoryAnalyzer.exe文件即可启动MAT工具,如下所示:

8091cabb80f6fed47ab5c89787932472.png

mat目录

点击File->Open heap dump 打开之前导出的dump文件,将会生成Overview选项,效果如图:

c6de76b546c259fef3a475111249083c.png

在Overview选项中,以饼状图的形式列举出了程序内存消耗的一些基本信息,其中每一种不同颜色的饼块都代表了不同比例的内存消耗情况。

点击overview右侧的panel,我们可以看到如下图所示的效果,里面列举了可能的泄漏点,并且对泄漏点进行了描述。

472a82e1d257943c6ebd381df675e1cc.png

疑似的泄漏点

再介绍一下我们工具栏上常用的一些功能:Dominator Tree,Histogram

Dominator Tree:

如果需要定位内存泄露的代码点,我们可以通过Dominator Tree菜单选项来进行排查。

Dominator Tree提供了一个列表。可以看到对象之间dominator关系树。从MAT的Dominator tree中可以看到占用内存最大的对象以及每个对象的Dominator。

a5ef743af23df45326cd1f2bcb295efa.png

Dominator Tree

点开“+”符号,可以进一步查看内层应用情况,同时还可以看到对应类对象的属性值,如下所示:

3cd45b895778eb211f5b36df03ded7e1.png

展开图

可以看到,我们这边有一大堆的Studen一直占用着内存,没有被回收,那么肯定是有问题的。

因为咱们的实验代码比较简单,但是在生产环境上肯定是没有这么清晰的,所以通常在排查内存泄漏的时候,我们还需要排除掉虚引用/弱引用/软引用等引用链,查看强引用。(强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。)

那么如何排除掉虚引用/弱引用/软引用等引用链呢?如下图所示,选择exclude all phantom/weak/soft etc.references,意思是查看排除虚引用/弱引用/软引用等的引用链,因为被虚引用/弱引用/软引用的对象可以直接被GC给回收,我们要看的就是某个对象否还存在Strong 引用链(在导出HeapDump之前要手动出发GC来保证),如果有,则说明存在内存泄漏,然后再去排查具体引用。

392695d78201c8f2bfe1a874b1ee214d.png

排除其他引用

Dominator Tree讲完了,下面我们来讲一下工具栏上还有一个好用的功能Histogram

Histogram

Histogram清晰的列出了每个类的Objects,Shallow Heap,Retained Heap,关于Shallow Heap和Retained Heap的具体意义,在有空的时候我会单独讲解,现在可以先理解为对象本身占用的内存大小和该对象被回收时可以释放的内存大小。

365f2f17917cd76f3539b4c8a04d7ef6.png

Histogram通过正则过滤

当我们找到疑似存在泄漏的类之后,我们可以进行进一步分析,排除引用。

f5e89c5e75bff8aa0cfb732946c8511b.png

排除引用

还有一些会在平时用到的右键菜单中的按钮:

List objects :

with incoming references 引用到该对象的对象

with outcoming references 被该对象引用的对象

Show objects by class :

incoming references 引用到该对象的对象

outcoming references 被该对象引用的对象

总结

今天为大家带来了jmap+mat内存分析,感兴趣的小伙伴们可以收藏并关注我,为大家持续带来干货。

cc403135bf8e7e8ee493b1836bb890f2.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值