内存泄漏

在应用服务器查询dump文件(内存过大)
jmap -dump:format=b,file=jconsole.hprof 9473
文件地址:/root
分析工具MAT(Memory Analyzer Tool)
参考网址:
https://blog.csdn.net/alcoholdi/article/details/55667078
https://www.cnblogs.com/wyb628/p/8567617.html
在这里插入图片描述

**`常用到的功能:`**

在这里插入图片描述
在这里插入图片描述
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190702140409278.png
Overview视图,即概要界面,显示了概要的信息,并展示了MAT常用的一些功能。
Details 显示了一些统计信息,包括整个堆内存的大小、类(Class)的数量、对象(Object)的数量、类加载器(Class Loader)的数量。
Biggest Objects by Retained Size 使用饼图的方式直观地显示了在JVM堆内存中最大的几个对象,当光标移到饼图上的时候会在左边Inspector和Attributes窗口中显示详细的信息。
Actions 这里显示了几种常用到的操作,算是功能的快捷方式,包括 Histogram、Dominator Tree、Top Consumers、Duplicate Classes。
Reports 列出了常用的报告信息,包括 Leak Suspects和Top Components。
在这里插入图片描述
直方图,可以查看每个类的实例(即对象)的数量和大小。
在这里插入图片描述
MAT提供了一个对象查询语言(OQL),跟SQL语言类似,将类当作表、对象当作记录行、成员变量当作表中的字段。通过OQL可以方便快捷的查询一些需要的信息,是一个非常有用的工具。

在这里插入图片描述
此工具可以查看生成Heap Dump文件的时候线程的运行情况,用于线程的分析。
在这里插入图片描述
可以查看分析完成的HTML形式的报告,也可以打开已经产生的分析报告文件,子菜单项如下图所示:
在这里插入图片描述
使用MAT打开一个Dump文件时,会弹出向导窗口,保持默认选项,点Finish,就会导向 Leak Suspects内存泄露报告页面
如果打开Dump时跳过了的话,也可以从其它入口进入,如
(1)工具栏上的 Run Expect System Test > Leak Suspects
(2)Overview页面的Reports部分
Leak Suspects 是MAT帮我们分析的可能有内存泄露嫌疑的地方,可以体现出哪些对象被保持在内存中,以及为什么它们没有被垃圾回收
MAT提供了一个很贴心的功能,将报告的内容压缩打包到一个zip文件,并放在原始堆转储文件的目录下,一般命名为“xxx_Leak_Suspects.zip”,xxx是dump文件的名字,如果需要和同事一起分析这个内存问题的话,只需要把这个小小的zip包发给他就可以了,不需要把整个堆文件发给他。并且整个报告是一个HTML格式的文件,用浏览器就可以轻松打开
在这里插入图片描述
提供了在分析过程中用到的工具,通常都集成在了右键菜单中,在后面具体举例分析的时候会做详细的说明。
这里仅针对在 Overview 界面中的 Acations中列出的两项进行说明:

Top Consumers 按类、类加载器和包分别进行查询,并以饼图的方式列出最大的几个对象。菜单打开方式如下:
在这里插入图片描述
Duplicate Classes 列出被加载多次的类,结果按类加载器进行分组,目标是加载同一个类多次被类加载器加载。使用该工具很容易找到部署应用的时候使用了同一个库的多个版本。菜单打开方式如下图:
在这里插入图片描述
在这里插入图片描述
通过十六进制的地址查找对应的对象,见下图:
在这里插入图片描述

**常见的内存泄漏,总结起来只有3类**

1.跟静态(static)相关的。

比如说单例中使用到Context,传递了Activity这个Context而不是ApplicationContext。比如有些博主举例用 static 修饰一个View对象。比如static修饰了一个集合类,这集合类有很多元素或者里面元素都很大。

2.任务型工作。

比如Handler导致的内存泄漏,是因为 postDelayed 或者 sendMessageDelayed 发送了延时任务,详情看我之前文章。还有 AsyncTask 任务或者其他耗时网络请求。应该在离开(一般退出Activity)的时候取消掉。

3.一些资源打开或注册后,需要及时的关闭或注销。

 **Dominator Tree--支配(对象)树**

支配树,列出Heap Dump中处于活跃状态中的最大的几个对象,默认按 retained size进行排序,因此很容易找到占用内存最多的对象。


一波概念解释:
----------Shallow Size ----------
对象自身占用的内存大小,不包括它引用的对象。
针对非数组类型的对象,它的大小就是对象与它所有的成员变量大小的总和。当然这里面还会包括一些java语言特性的数据存储单元。
针对数组类型的对象,它的大小是数组元素对象的大小总和。
----------Retained Size -----------
Retained Size=当前对象大小+当前对象可直接或间接引用到的对象的大小总和。(间接引用的含义:A->B->C, C就是间接引用)
换句话说,Retained Size就是当前对象被GC后,从Heap上总共能释放掉的内存。
不过,释放的时候还要排除被GC Roots直接或间接引用的对象。他们暂时不会被被当做Garbage。
<备注:GC(Garbage Collection):JAVA/.NET中的垃圾回收器。)
有了GC,程序员就不需要再手动的去控制内存的释放。当Java虚拟机(VM)或.NETCLR发觉内存资源紧张的时候,就会自动地去清理无用对象(没有被引用到的对象)所占用的内存空间(这里的说法略显粗略,事实上何时清理内存是个复杂的策略)。如果需要,可以在程序中显式地使用System.gc() / System.GC.Collect()来强制进行一次立即的内存清理。Java提供的GC功能可以自动监测对象是否超过了作用域,从而达到自动回收内存的目的,Java的GC会自动进行管理,调用方法:System.gc() 或者Runtime.getRuntime().gc();>
在这里插入图片描述
在这里插入图片描述


在这里插入图片描述

 **`Histogram`**

会根据类名来区分列举出表格,后面3个列是类型的对象个数,Shallow Size和Retained Size。默认是按照Shallow Size排序,也可以更改排序方式。在这里插入图片描述

**List Object**

with outgoing references可以列出这个对象里所持有的所有对象们。

with incoming references可以列出所有持有这个对象的对象们。
在这里插入图片描述

. **定位溢出源**

Histogram视图和Dominator Tree视图的角度不同,前者是基于类的角度,后者是基于对象实例的角度,并且可以更方便的看出其引用关系。
首先,在两个视图中找出疑似溢出的对象或者类(可以通过Retained Heap排序,并且可以在Class Name中输入正则表达式的关键词只显示指定的类名),然后右键选择Path To GC Roots(Histogram中没有此项)或Merge Shortest Paths to GC Roots,然后选择 exclude all phantom/weak/soft etc. reference:
在这里插入图片描述
GC Roots意为GC根节点,其含义见上面的 GC Roots和Reference Chain 部分,后面的 exclude all phantom/weak/soft etc. reference 意思是排除虚引用、弱引用和软引用,即只剩下强引用,因为除了强引用之外,其他的引用都可以被JVM GC掉,如果一个对象始终无法被GC,就说明有强引用存在,从而导致在GC的过程中一直得不到回收,最终就内存溢出了。

通过结果就可以很方便的定位到具体的代码,然后分析是什么原因无法释放该对象,比如被缓存了或者没有使用单例模式等等。
在这里插入图片描述
上图中保留了大量的VelocitySqlBulder的外部引用,后来查看了代码,原来每次调用的时候都实例化一个新的对象,由于VelocitySqlBulder类是无状态的工具类,因此修改为单例方式就可以解决这个问题。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值