前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >内存分析工具MAT的使用入门

内存分析工具MAT的使用入门

作者头像
用户7634691
发布2020-08-10 16:20:05
7.8K0
发布2020-08-10 16:20:05
举报
文章被收录于专栏:犀牛饲养员的技术笔记

MAT工具介绍

工欲善其事必先利其器,学会使用工具也是一种本领。本篇文章就把自己之前工作中用到的一个内存分析工具给大家介绍下。

内存分析工具MAT(Memory Analyzer Tool)是一款 JVM 的内存分析工具,在实际的工作中可以帮助我们解决生成上内存占用过高等问题。

我之前用 MAT 是在 eclipse上使用,前者是后者的一个插件。后来换到 IDEA 才知道原来 MAT 也有独立的可运行版本。它的下载地址如下:

http://www.eclipse.org/mat/downloads.php

测试代码

我们先准备一段简单的代码,这个代码会导致 JVM 堆内存溢出,方便我们演示 MAT 的效果。

代码语言:javascript
复制
public static void main(String[] args) throws InterruptedException {
        Map<String,Tom> map = new HashMap<String,Tom>();
        int counter = 1;
        while(true) {
            Thread.sleep(10);
            Tom tom = new Tom();
            String [] friends = new String[counter];
            for (int i = 0; i < friends.length; i++) {
                friends[i] = "friends"+i;
            }
            tom.setAge(counter);
            tom.setName("tom"+counter);
            tom.setFriends(friends);
            map.put(tom.getName(),tom);
            if(counter%100==0)
                System.out.println("put"+counter);
            counter++;
        }
    }

很好理解的一段代码,一个无限循环,不断的往map里添加名为Tom的对象,而且每次循环new出来的对象的friends属性还在不断的扩大。

然后我们使用启动下面这个启动参数运行代码,

代码语言:javascript
复制
-Xms200m -Xmx200m  -XX:+HeapDumpOnOutOfMemoryError

参数指定了堆内存大小是200m,这个大小我们的测试代码很快就会用完,然后报错。

启动代码,运行一段时间后报错如下,

代码语言:javascript
复制
java.lang.OutOfMemoryError: GC overhead limit exceeded
Dumping heap to java_pid1398.hprof ...
Heap dump file created [239632332 bytes in 0.865 secs]

从这个报错我们可以获取几个信息,首先是错误类型是内存溢出,原因是超出了GC的限制。

其次,我们看到程序出错时的内存快照 dump 到了一个名为 java_pid1398.hprof 的文件中了。这个文件就是可以用于 MAT 工具分析的dump文件。

除了上面的通过 -XX:+HeapDumpOnOutOfMemoryError 参数来dump内存文件之外, 还可以通过 jmap 命令来导出的内存快照。这里不做详述了。

内存分析

我们现在根据 MAT 的分析,从几个维度来分析下代码中的问题。

MAT 工具打开前面的 dump 文件,会先看到下面这种图,

从预览图,可以看到有个应用占用了总的堆内存的大部分,高达184M(程序运行分配的堆内存是200M)。说明这个应用肯定有问题,值得我们继续往下分析。

我们先看看工具给我们的一个判断,找到 Leak Suspects,点击去。

从描述上看到,主线程有个本地变量占用了很大内存,这个变量是 HashMap 的实例。

哈哈,根据上面的代码,不得不说 MAT 还是很牛叉的,对于内存泄漏点定位的很准确。

不过有时候,我们还是需要手动分析下我们还是回到之前的预览页面,找到 Histogram 点进去,如下图:

shallow heap 指的是对象自身占用的内存大小,不包括它引用的对象。 针对非数组类型的对象,它的大小就是对象与它所有的成员变量大小的总和。当然这里面还会包括一些java语言特性的数据存储单元。 针对数组类型的对象,它的大小是数组元素对象的大小总和。

我们看到排在前面的是占用内存比较多的, char[] 这个明显是String里引用造成的(string里用char[] 存储数据),我们之间来看String是被谁引用的,

很清晰,Tom对象的friends属性消耗了很多内存。

这里说明下,

  • with incoming references 表示的是 当前查看的对象,被外部应用
  • with outGoing references 表示的是 当前对象,引用了外部对象

同理,我们可以继续分析下面几个类,最终都会定位到内存吃紧的原因是 hashmap 里短时间塞了大量的 Tom 对象撑爆了内存。

参考:

https://www.cnblogs.com/hanlinhu/p/10174185.html

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-10-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 犀牛的技术笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • MAT工具介绍
  • 测试代码
  • 内存分析
相关产品与服务
数据保险箱
数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档