排查内存泄漏最简单和直观的方法

排查内存泄漏最简单和直观的方法,第1张

内存泄漏无疑会严重影响用户体验,一些本应该废弃的资源和对象无法被释放,导致手机内存的浪费,app使用的卡顿,那么如何排查内存泄漏呢?

当然,首先我门有google的官方文档可以参考:

大部分博客的方法也来自于此。总的来说,就是使用android studio 的monitor memory功能监测app主进程占用的内存,触发GC *** 作,而后观察内存的占用情况,如果在使用的过程中内存不断增加,没有回落, 很有可能 发生了内存泄漏,这时候就需要导出内存分配的具体详情进行深入分析了。

但是事实上,通过观察这个内存曲线的曾场来或者是观察allocate tracker中的allocate data数值的增长来检测是否有内存泄漏问题,真的很玄,因为往往内存泄漏发生了,但是GC仍然可以通过回收其他对象的方式腾出空间,导致这个数据的变化基本看不出来,甚至是减小的,所以我觉得这种方式, 就像是让你用手掌去感知婴儿的体温,去检测确定这个婴儿有没有发烧一样,非常不靠谱不准确。

那么,重点来了,我的方法,简单直观,保准你一学就会!

先说一个terminal指令: 

这条指令是用来查询这个进程所占用的内存的具体详情的,通过这条指令可以看到当前app在手机中占用的具体的堆内存大小,view的数量, activity的数量 ,等等。如下图:

其中activity数目是非常关键的一个信息,可以帮助我们快速地检测出内存泄漏。我们可以反复地进入退出需要测试的目标activity,如果在反复进入退出之后,用terminal执行上面的语句查询当前的内存情况,如果发现activity数量一直在增长,那么内存泄露一定是发生了!

内存泄漏已经发生,如何定位原因呢?

如下图,在android studio中开始memory monitor,点击init GC,反复进入退出发生了内存泄漏的activity,这时候点击生成内存文件,这之后android studio会自动打开生成的.hprof文件。选中该文件转化成标准的hrof文件。

用MAT工具打开生成的.hprof文件,点击如下所示的图标,可以看到内存中的对象列表。

考虑到大内存的泄漏都是因为Activity被destroy之后却仍然被其他对象持有而造成的,因此首先解决棘手问题,直接搜索Activity,如下。发现有Activity的实例个数是3,跟实际不符,明显这个activity导致内存泄漏了,按照如图的方式找到它的引用,也就是导致内存泄漏的幕后凶手!

可以看到这个例子中的内存泄漏是由一个HandlerThread引发的,那么找到这个问题的位置,在合适的地方(如ondestroy)将这个handler thread释放即可。

如下图所示: 在android studio中打开生成的hprof文件,在右侧边栏会出现的Analyzer Tasks工具,点击执行图标,即可出现检测分析的结果,得到哪些activity被泄漏了,这些被泄漏的activity被谁引用了。

可以看到内存泄漏由AsyncHandler引起,需要在activity生命周期结束的时候进行释放。

方法2不用安装MAT工具,更加便捷哦~

 有问题可以留言,谢谢您的阅读~~

内存快照是一种在 Java 程序运行时打的内存快照,用来在程序运行时查看堆内存中的对象信息和状态。

要快速启动 Java 内存快照,你需要以下步骤:

在命令行中运行 Java 程序时,需要使用 -XX:+HeapDumpOnOutOfMemoryError 参数。这会在程序遇到内存溢出时自动生成内存快照。

当程序遇到内存溢出时,会在程序所在的目录中生成一个 hprof 文件,该文件就是内存快照。

使用工具来打开和查看 hprof 文件

最近在写性能优化专题相关文章,依次写了“Android电量优化全解析”、“Android性能优化全解析”、“Android渲染优化解析”、“Android计算优化解析”。文章中有提到许多性能优化的工具,但由于文章重点都是如何分析性能相关的论述,对工具的使用介绍大都是简单略过,下面简单介绍下性能优化工具-MAT(Memory Analyzer Tool)使用,介绍的顺序为:

MAT工具全称为Memory Analyzer Tool,一款详细分析Java堆内存的工具,该工具非常强大,为了使用该工具,我们需要hprof文件。但是该文件不能直接被MAT使用,需要进行一步转化,可以使用hprof-conv命令来转化,但是Android Studio可以直接转化,转化方法如下:

1.选择一个hprof文件,点击右键选择Export to standard .hprof选项。

2.填写更改后的文件名和路径。

点击OK按钮后,MAT工具所需的文件就生成了!

下面我们用MAT来打开转换后的doctorq.hprof文件:

1.打开MAT后选择File->Open File选择我们刚才生成的doctorq.hprof文件

2.选择该文件后,MAT会有几秒种的时间解析该文件,有的hprof文件可能过大,会有更长的时间解析,解析后,展现在我们的面前的界面如下:

这是个总览界面,会大体给出一些分析后初步的结论。

该视图会首页总结出当前这个Heap dump占用了多大的内存,其中涉及的类有多少,对象有多少,类加载器,如果有没有回收的对象,会有一个连接,可以直接参看(图中的Unreachable Objects Histogram)。

比如该例子中显示了Heap dump占用了41M的内存,5400个类,96700个对象,6个类加载器, 然后还会有各种分类信息。

会列举出Retained Size值最大的几个值,你可以将鼠标放到饼图中的扇叶上,可以在右侧看出详细信息:

图中灰色区域,并不是我们需要关心的,他是除了大内存对象外的其他对象,我们需要关心的就是图中彩色区域,比如图中2.4M的对象,我们来看看该对象到底是啥

该对象是一个Bitmap对象,你如果想知道该对象到底是什么图片,可以使用图片工具gimp工具浏览该对象。

histogram视图主要是查看某个类的实例个数,比如我们在检查内存泄漏时候,要判断是否频繁创建了对象,就可以来看对象的个数来看。也可以通过排序看出占用内存大的对象:

默认是类名形式展示,你也可以选择不同的显示方式,有以下四种方式:

下面来演示一下:

该视图会以占用总内存的百分比来列举所有实例对象,注意这个地方是对象而不是类了,这个视图是用来发现大内存对象的。这些对象都可以展开查看更详细的信息,可以看到该对象内部包含的对象:

这个视图会展示一些可能的内存泄漏的点,比如上图上图显示有3个内存泄漏可疑点,我们以Problem Suspect 1为例来理解该报告,首先我们来看该可疑点详细信息:

上面信息显示ImageCahe类的一个实例0xa50819f8占用了14.19%的内存,具体值为5147200字节(5147200/1024/1024=4.9M),并存放在LinkedHashMap这个集合中,然后我们点击Details跳转到更详细的页面:

这样我们就能找到在我们的app源码中造成该泄漏可疑点的地方,很容易去定位问题。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/11726207.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-18
下一篇 2023-05-18

发表评论

登录后才能评论

评论列表(0条)

保存