手机需要有root权限。
1.eclipse中选中要查看的应用包名,点击下图中图标
2.点击Heap中的Cause GC按钮,刷新视图。
Heap视图界面会定时刷新,在对应用的不断操作过程中就可以看到内存使用的变化。
怎么判断当前进程是否有内存泄露呢?
这里需要注意一个值:VM Heap页面中部有一个data object选项,即数据对象,也就是我们的程序中大量存在的类的对象。
在data object一行中有一列是“Total Size”,其值就是当前进程中所有Java数据对象的内存总量,一般情况下,这个值的大小决定了是否会有内存泄露。
可以据此判断内存有泄露:
a).不断的操作当前应用,或者重复某一动作,注意观察data object的Total Size值。
b).正常情况下Total Size值都会稳定在一个有限的范围内,也就是说如果程序中的代码逻辑良好,没有创建的对象不被GC机制正常回收的情况,即便我们不断的操作生成很多对象,而在虚拟机不断的进行垃圾回收的过程中,这些对象都被正常回收了,内存使用量会保持在一个比较稳定的水平。
c).如果代码中存在对象引用没有释放的情况,则data object的Total Size值在每次GC后不会有明显的回落,随着操作次数的增多Total Size的值会越来越大。
正常情况下,一个虚拟机的进程的内存在64M,如果内存泄露会发现Heap Size在不断的逼近64M,一旦达到这个值时,就会出现退出应用等情况。
发生内存泄露时,Total Size的值越来越大时,按下“Dump HPROF file”按钮,生成分析报告
分析报告如下图:
通过上面的概览,我们对内存占用情况有了一个总体的了解。
点击上图中的Reports -- > Leak Suspects则可以进一步看到更详细的内存泄露疑点。
分析三步曲
通常我们都会采用下面的“三步曲”来分析内存泄露问题:
首先,对问题发生时刻的系统内存状态获取一个整体印象。
第二步,找到最有可能导致内存泄露的元凶,通常也就是消耗内存最多的对象。
接下来,进一步去查看这个内存消耗大户的具体情况,看看是否有什么异常的行为。
下面将用一个基本的例子来展示如何采用“三步曲”来查看生成的分析报告。
查看报告之一:内存消耗的整体状况
在报告上最醒目的就是一张简洁明了的饼图,从图上我们可以清晰地看到一个可疑对象消耗了系统50%以上的内存。
在图的下方还有对这个可疑对象的进一步描述,我们可以看到内存是由byte[]实例消耗的,system class loader负责这个对象的加载。这段描述非常短,但我相信您已经可以从中找到很多线索了,比如哪个类占用了绝大多数的内存,它属于哪个组件等等。
接下来,我们应该进一步去分析问题,为什么一个byte[]会占据系统这么多内存,谁阻止了垃圾回收机制对它的回收。
查看报告之二:分析问题的所在
首先我们简单回顾下Java的内存回收机制,内存空间中垃圾回收的工作由垃圾回收器(Garbage Collector, GC)完成的,它的核心思想是:对虚拟机可用内存空间,即堆空间中的对象进行识别,如果对象正在被引用,那么称其为存活对象,反之,如果对象不再被引用,则为垃圾对象,可以回收其占据的空间,用于再分配。
在垃圾回收机制中有一组元素被称为根元素集合,它们是一组被虚拟机直接引用的对象,比如,正在运行的线程对象,系统调用栈里面的对象以及被system class loader所加载的那些对象。堆空间中的每个对象都是由一个根元素为起点被层层调用的。因此,一个对象还被某一个存活的根元素所引用,就会被认为是存活对象,不能被回收,进行内存释放。因此,我们可以通过分析一个对象到根元素的引用路径来分析为什么该对象不能被顺利回收。如果说一个对象已经不被任何程序逻辑所需要但是还存在被根元素引用的情况,我们可以说这里存在内存泄露。
现在,让我们开始真正的寻找内存泄露之旅,点击“Details”链接,可以看到详细的分析报告。
1.我们查看下从GC根元素到内存消耗聚集点的最短路径:
我们可以很清楚的看到整个引用链,内存聚集点是一个拥有大量对象的集合,如果你对代码比较熟悉的话,相信这些信息应该能给你提供一些找到内存泄露的思路了。
接下来,我们再继续看看,这个对象集合里到底存放了什么,为什么会消耗掉如此多的内存。
打开Accumulated Objects in Dominator Tree查看详细信息。