一.概述
首先来普及一下什么是内存泄露:
内存泄露是指对象的内存在分配之后无法通过程序的执行逻辑释放对该对象的引用,导致不能回收该对象所占内存。
内存泄露会导致以下情况:
1.程序卡顿,响应速度慢(内存占用高时JVM虚拟机会频繁触发GC)
2.莫名消失(当你的程序所占内存越大,它在后台的时候就越可能被干掉。反之内存占用越小,在后台存在的时间就越长)
3.直接崩溃(OutOfMemoryError)
内存泄露在Android开发中是很容易遇到的,但是我们一般很难察觉到,那么此时就要借助一些工具来帮助我们分析内存情况了,今天就来看看如何使用进行内存泄露分析。
二.分析
所需要的工具
- Android Studio 1.1 或者更高版本
- Eclipse Memory Analyzer
实例代码1:
public class MainActivity extends Activity {
TextView textView;
public static final String TAG = MainActivity.class.getSimpleName();
List list = new ArrayList();
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
while (true)
{
Person person=new Person();
list.add(person);
person=null;
}
}
}
这是一个非常基础的Activity.我们使用了一个死循环,不断向集合中添加对象,毫无疑问,当程序运行起来的时候直接就会出现下面的情况:
没错,就是内存溢出(OOM),下面我们看看如何使用MAT这个工具来分析是什么原因导致了内存溢出呢。
当程序崩溃后,我们切换到DDSM视图,
首先我们点击当前进程的名称,然后点击上方的Update Heap按钮,然后点击Dump HPROF file按钮,这是如果你的Eclipse装有MAT插件的话,就会自动打开hprof文件。
然后我们在下面可以看见可疑对象描述报告图1
我们点击Detail,
图2,从根元素到内存消耗聚集点的最短路径
继续向下看,
图3,内存消耗对象信息
在这张图上,我们可以清楚的看到,这个对象集合中保存了大量 Person对象的引用,就是它导致的内存泄露。
至此,我们已经拥有了足够的信息去寻找泄露点,回到代码,我们发现,是下面的代码导致了内存泄露 :
while (true)
{
Person person=new Person();
list.add(person);
person=null;
}
总结
从上面的例子我们可以看到用 MAT 来进行堆转储文件分析,寻找内存泄露非常简单,尤其是对于新手而言,这是一个很好的辅助分析工具。但是,MAT 绝对不仅仅是一个“傻瓜式”内存分析工具,它还提供很多高级功能,比如 MAT 支持用 OQL(Object Query Language)对 heap dump 中的对象进行查询,支持对线程的分析等,有关这些功能的使用可以参考 MAT 的帮助文档。