性能优化——内存泄漏(2)工具分析篇

内存泄漏系列文章:
性能优化——内存泄漏(1)入门篇
性能优化——内存泄漏(2)工具分析篇
性能优化——内存泄漏(3)代码分析篇java

1、简述

在上一篇《性能优化——内存泄漏(1)入门篇》中,介绍了内存泄漏的基本概念,并举了一个Demo,结合简单的代码分析,猜想出Demo中存在内存泄漏,并用Android Studio自带的Memory Monitor证实了咱们的猜想,但开发中,业务逻辑可能比较复杂,对象引用繁多,难道都要这样去作代码分析吗?确定不行,程序员的精力有限,且“很懒”(追求效率),咱们须要工具来帮助咱们进行分析。下面就来看看都有什么神器吧。程序员

2、工具分析

一、System Information

System Information是Android Studio自带的分析工具,能够经过它来判断APP总体是否存在内存泄漏。性能优化

一个不存在内存泄漏的APP,在其退出并执行过GC后,APP中全部的View和Activity都会被销毁,因此,咱们能够根据退出后内存中View和Activity的数量来判断这个APP是否存在内存泄漏。操做以下:eclipse

以上一篇中的Demo为例:
运行APP-->打开一个Activity-->屏幕旋转-->点返回键(两次)直到到桌面-->执行GC-->System Information-->Memory Usage工具

经过上述操做,会生成一个txt文本,其中就记录着View和Activity的数量。以下图所示,它们的值都为0(主要看Activities),说明本APP不存在内存泄漏。相反的,只要值不为0,那么APP是存在内存泄漏的。post

这种方式只能判断整个APP是否存在内存泄漏,但没法知道哪里有内存泄漏,也没法得知是哪些对象引用形成的内存泄漏。性能

二、Analyzer Tasks

Analyzer Tasks 是Android Studio自带的分析工具,能够帮助咱们快速定位内存泄漏,并且使用上 very easy~优化

打开一个内存快照(.hprof文件),Android Studio的右侧会出现Analyzer Tasks。3d

打开Analyzer Tasks后,能够发现有2个选项和一个按钮,说明以下图所示,咱们须要的就是第一个"Detect Leaked Activities"。orm

执行任务后,下方的Analysis Results中会获得泄漏的Activity,并且直接定位到了MemoryLeakActivity[0],要上篇中获得的结果同样。

三、MemoryAnalyzer(MAT)

这工具,真心以为有点复杂,但功能比Android Studio自带的Analyzer Tasks要强大的多。

MemoryAnalyzer是基于eclipse开发的,是一个单独的软件,它也是对.hprof文件进行分析,但必须是标准的.hprof文件,能够从Android Studio中导出。

运行MAT,经过File-->Open Dump分别打开刚刚导出的test1.hprof和test2.hprof,选择Leak Suspects Report-->Finish。

分析的方式有两种,一种是单文件分析,一种是多文件分析,咱们先进行单文件分析。

1)单文件分析

切换到test2.hprof,打开Histogram。

点击Histogram后,会出来一个Histogram标签,会列出APP中全部类的实例个数,感受跟Android Studio的.hprof查看器差很少,MAT中的Objects至关于AS中查看器的Total Count。

经过包名筛选,找出了咱们本身写的代码,Android Studio的话能够经过切换视图来定位。能够发现MemoryLeakActivity的实例有2个,说明它可能存在泄漏,再联系以前在获取快照以前执行过GC,而这个Activity尚未销毁,说明这个Activity应该是泄漏了。好,到这里单文件分析就结束了。

2)多文件分析

分别将test1.hprof和test2.hprof的histogram添加到Compare Basket,详细操做以下图所示。

在Compare Basket中会有刚刚添加的两个.hprof,点击红色感叹号进行对比。

出来的Compared Tables列表跟Histogram很像,不过Objects和Shallow Heap标签都是成双成对。

同样,咱们只关心咱们本身的代码,因此经过Regex进行筛选。经过数据分析,能够知道,在旋转屏幕先后,MemoryLeakActivity的实例由1增长到了2,又由于test2.hprof是在执行了GC后获取的,因此能够断定MemoryLeakActivity在旋转屏幕后,内存泄漏了。

3)引用跟踪

经过单文件分析或多文件分析,咱们知道MemoryLeakActivity发生了内存泄漏(被别的实例引用致使没法被GC回收),因此回到test2.hporf的Histogram,筛选出MemoryLeakActivity,右击List objects-->with incoming references。

出来的结果有2大块,即对内存中的2个MemoryLeakActivity实例分别被引用的结果进行了分类,能够看到每一个MemoryLeakActivity都被好多个对象引用了。

结合上篇中提到的java中几个特殊类,咱们知道SoftReference、WeakReference和PhantomReference在GC通常不会形成内存泄漏,因此这些咱们能够无论,也说是说,咱们能够对它们进行排除。

对两个Activity分别排除软、弱、虚引用后,获得的结果分别以下:

简单分析下就知道了,第一个MemoryLeakActivity实例是泄漏的,引用它的对象就是CommonUtil。

3、总结

一、工具方面

我的仍是比较推荐使用Android Studio集成的System Information和Analyzer Tasks,主要是使用上方便快捷,还很简单,若是你是高手,而且须要有更强大的功能来帮助你检查APP中的内存泄漏的话,建议使用MAT,在网上多找些比较详细的文章看看,本文对MAT的介绍只是冰山一角。

二、操做方面

工具仅仅只是帮助咱们快速定位APP中的内存泄漏,并不能直接告诉咱们哪里有内存泄漏,实际开发中,须要咱们去猜想,去思考,要有清晰的思惟,千方百计的构思内存泄漏的断定依据。这须要咱们本身去摸索,积累必定的经验。最后,在获取内存快照(Dump Java Heap)以前,建议多点几回Initiate GC,等内存稳定成一条线时再获取内存快照。

相关文章
相关标签/搜索