当前位置:文档之家› Android 应用程序内存泄漏的分析

Android 应用程序内存泄漏的分析

Android 应用程序内存泄漏的分析
以前在学校里学习Java的时候,总是看到说,java是由垃圾收集器(GC)来管理内存回收的,
所以当时形成的观念是Java不会产生内存泄漏,我们可以只管去申请内存,不需要关注内存回收,
GC会帮我们完成。呵呵,很幼稚的想法,GC没那么聪明啊,理论及事实证明,我们的Java程序也
是会有内存泄漏的。

(一) Java内存泄漏从何而来
一般来说内存泄漏有两种情况。一种情况如在C/C++语言中的,在堆中的分配的内存,没
有将其释放,或者是在没有将其释放掉的时候,就将所有能访问这块内存的方式都删掉(如指
针重新赋值);另一种情况则是在内存对象明明已经不需要的时候,还仍然保留着这块内存和它
的访问方式(引用)。第一种情况,在Java中已经由于垃圾回收机制的引入,得到了很好的解
决。所以,Java中的内存泄漏,主要指的是第二种情况。

(二) 需要的工具
1. DDMS—Update heap Gause GC
Heap 是DDMS自带的一个很不错的内存监控工具,下图红色框中最左边的图标就是该
工具的启动按钮,它能在Heap视图中显示选中进程的当前内存使用的详细情况。下图
框中最右边的是GC工具,很多时候我们使用Heap监控内存的时候要借助GC工具,点
击一次GC按钮就相当于向VM请求了一次GC操作。中间的按钮是Dump HPROF file,它
的功能相当于给内存拍一张照,然后将这些内存信息保存到hprof文件里面,在使用我
们的第二个工具MAT的时候会使用到这个功能。

2. MAT(Memory Analyzer Tool)
Heap工具能给我们一个感性的认识,告诉我们程序当前的内存使用情况和是否存在内存
泄漏的肯能性。但是,如果我们想更详细,更深入的了解内存消耗的情况,找到问题所
在,那么我们还需要一个工具,就是MAT。这个工具是需要我们自己去下载的,可以下
载独立的MAT RCP 客户端,也可以以插件的形式安装到Eclipse里面,方便起见,推荐
后者。
安装方法:
A. 登录官网http://www.eclipse.org/mat/downloads.php
B. 下载MAT Eclipse插件安装包(红框所示,当然你也可是选择Update Site在线安装,
个人觉得比较慢)
C. 安装
在Eclipse里面安装新软件,选择刚才下载的本地安装包进行安装

(三) 案例分析
工具准备好了,那就来看看怎么使用。我们以Q+ for Pad为例,看看查找好友功能是否存在
内存泄漏。
1. 打开 eclipse 并切换到 DDMS 透视图,同时确认 Devices 、 Heap 和 logcat 视图已经打

开了。
2. 将Pad设备链接到电脑,并确保使用“ USB 调试”模式链接
3. 启动我们的Q+ for Pad应用,此时我们能看到下图所示的情况,Q+ Pad有两个进程

4. 选中main进程,点击Update Heap按钮,再点击GC按钮,查看该进程当前堆内存的使用
情况
如何才能知道我们的程序是否有内存泄漏的可能性呢。这里需要注意一个值:Heap视
图中部有一个Type叫做data object,即数据对象,也就是我们的程序中大量存在的类
型的对象。在data object一行中有一列是“Total Size”,其值就是当前进程中所有Java
数据对象的内存总量,一般情况下,这个值的大小决定了是否会有内存泄漏。可以这样
判断:
a) 不断的操作当前应用,同时注意观察data object的Total Size值;
b) 正常情况下Total Size值都会稳定在一个有限的范围内,也就是说由于程序中的的代
码良好,没有造成对象不被垃圾回收的情况,所以说虽然我们不断的操作会不断的生成
很多对象,而在虚拟机不断的进行GC的过程中,这些对象都被回收了,内存占用量会
会落到一个稳定的水平;
c) 反之如果代码中存在没有释放对象引用的情况,则data object的Total Size值在每
次GC后不会有明显的回落,随着操作次数的增多Total Size的值会越来越大,直到到
达一个上限后导致进程被kill掉。
5. 输入昵称,查找联系人,在查到的结果中不断向下翻页,最后退出(这个时候程序会不

断的拉取联系人的头像,这是我们要关注的),然后我们点击下GC按钮,手动触发下垃
圾回收,结果截图如下,图中红色标记的地方可以看出,执行查找联系人操作后,这两
个数值明显增加了,GC操作也无法使之下降,我们可以怀疑,这个操作导致了内存泄漏。

6. 使用MAT进一步分析,找到问题的根源。之前我们已经安装了MAT插件,所以这里我
们只要选中main进程,点击Dump HPROF file按钮,就会跳转到MAT视图。在弹出的对
话框中选择报告类型,一般选第一个就行。

点击完成后,MAT会自动生成报告,列出几个内存占用比较大的可疑对象,MAT不会明
确告诉我们这就是泄露,因为它也不知道这个东西是不是程序还需要的,只有程序员自
己知道。图中很明显的占用内存较大的是头像资源,并且当退出查找联系人功能后,这
些资源是需要释放的,陌生人的头像我们不需要缓存在内存里面。
点击Domain Tree按钮,可以按包进行分组。点开树形列表,可以更详细的看到类对象
占用内存的大小。其中,Shallow Heap表示实例的内存使用总和,Retained Heap表示所
有类实例被分配的内存总和,里面也包括他们所有引用的对象。

从生成的数据中,我们发现有一千多个HashMapEntry对象,针对单个HashMapEntry对
象继续追踪,最后找到了一个6KB左右的Bitmap,应该就是我们的头像资源。

因此,为了回收内存,我们必须把刚才查找好友保存在内存中的头像资源释放。通过使
用Heap 和MAT工具,能够更好的帮助测试人员发现及定位内存泄漏问题,也能帮助我
们发下性能问题,找到内存优化的点。

相关主题