内存分析工具

内存分析工具

1. Lint 

使用 Lint 代码静态检查

1. Lint 是 Android Studio 自带的工具,使用很简单找到 Analyze -> Inspect Code 然后选择想要扫面的区域即可。


2. 选择 Lint 扫描区域。

内存分析工具_第1张图片

3. 对可能引起性能问题的代码,Lint 都会进行提示。

内存分析工具_第2张图片


2. Memory Monitor

    Memory Monitor可以轻松地监视应用程序的性能和内存使用情况,以便于找到被分配的对象,定位内存泄漏,并跟踪连接设备中正在使用的内存数量。它的作用如下:
    实时显示可用的和分配的Java内存的图表。
    实时显示垃圾收集(GC)事件。
    启动垃圾收集事件。
    快速测试应用程序的缓慢是否与过度的垃圾收集事件有关。

    快速测试应用程序崩溃是否与内存耗尽有关。

1. 一般在 Android Studio 的底部可以找到 Android Monitor。

内存分析工具_第3张图片

2.当前 App的内存变动比较大,很有可能出现了内存泄漏。 点击 Dump Java Heap,等一段时间会自动生成 Heap Snapshot 文件。

内存分析工具_第4张图片

3. 在 图片中可以找到 hprof 文件。

内存分析工具_第5张图片

4. 在右侧找到 Analyzer Tasks 并打开,点击图中 Perform Analysis 按钮开始分析。

内存分析工具_第6张图片

5. 通过分析结果可以看到 TestActivity 泄漏了,从左侧 Reference Tree 中可以看到是 TestActivity 中的 context 泄露了。

内存分析工具_第7张图片


3. Allocation Tracker

AS和DDMS中都有Allocation Tracker,
使用的步骤为: 
    1.运行需要监控的应用程序。 
    2.点击AS面板下面的Android图标,并选择Monitors选项。 
    3.点击Start Allocation Tracking按钮,这时Start Allocation Tracking按钮变为了Stop Allocation Tracking按钮。 
    4.操作应用程序。 
    5.点击Stop Allocation Tracking按钮,结束快照。这时Memory Monitor会显示出捕获快照的期间。

6.过几秒后就会自动打开一个窗口,显示当前生成的alloc文件的内存数据。

2. alloc文件分析

自动打开的alloc文件窗口如下图所示。 

该alloc文件显示以下信息:

说明
Method 负责分配的Java方法
Count 分配的实例总数
Total Size 分配内存的总字节数


目前的菜单选项是Group by Method我们也可以选择 Group By Allocator,如下图所示。 

可以选择列表中的一项,单击鼠标右键,在弹出的菜单中选择jump to the source就可以跳转到对应的源文件中。 
除此之外,还可以点击Show/Hide Chart按钮来显示数据的图形化,如下图所示。 


4. Heap Dump

Heap Dump的主要功能就是查看不同的数据类型在内存中的使用情况。它可以帮助找到大对象,也可以通过数据的变化发现内存泄漏。

打开Android Device Monitor工具,在左边Devices列表中选择要查看的应用程序进程,点击Update Heap按钮(装有一半绿色液体的圆柱体),在右边选择Heap选项,并点击Cause GC按钮,就会开始显示数据。每次点击Cause GC按钮都会强制应用程序进行垃圾回收,并将清理后的数据显示在Heap工具中。如下图所示。

从上图可以看出,Heap工具共有三个区域,分别是总览视图(标识1)、详情视图(标识2)和内存分配柱状图(标识2)。

 总览视图

其中总览视图可以查看整体的内存情况,表中的显示信息如下所示。

说明
Heap Size 堆栈分配给该应用程序的内存大小
Allocated 已分配使用的内存大小
Free 空闲的内存大小
%Used 当前Heap的使用率(Allocated/Heap Size)
Objects 对象的数量

结合上表和上图,在总览视图获得的信息就是:堆栈分配给当前的应用程序的内存大小为2.346MB,已分配的内存为1.346MB,空闲的内存为1MB,当前Heap的使用率为57.37%,对象的数量为24058个。

 详情视图

详细视图展示了所有的数据类型的内存情况,表中列的信息如下所示。

说明
Type 数据类型
Total Size 总共占用的内存大小
Smallest 将该数据类型的对象从小到大排列,排在第一个的对象所占用的内存
Largest 将该数据类型的对象从小到大排列,排在最后一个的对象所占用的内存
Median 将该数据类型的对象从小到大排列,排在中间的对象所占用的内存
Average 该数据类型的对象所占用内存的平均值

除了列的信息,还有行信息:

说明
free 内存碎片
data object 对象
class object
1-byte array (byte[],boolean[]) 1字节的数组对象
2-byte array (short[],char[]) 2字节的数组对象
4-byte array (object[],int[],float[]) 4字节的数组对象
6-byte array (long[],double[]) 8字节的数组对象
non-Java object 非Java对象

行信息中比较重要的是free,它与总览视图中的free的含义不同,它代表内存碎片。当新创建一个对象时,如果碎片内存能容下该对象,则复用碎片内存,否则就会从free空间(总览视图中的free)重新划分内存给这个新对象。free是判断内存碎片化程度的一个重要的指标。 

此外,1-byte array这一行的信息也很重要,因为图片是以byte[]的形式存储在内存中的,如果1-byte array一行的数据过大,则需要检查图片的内存管理了。

 检测内存泄漏

Heap Dump也可以检测内存泄漏。在左边Devices列表中选择要查看的应用程序进程,点击Update Heap按钮(装有一半绿色液体的圆柱体),在右边选择Heap选项,并点击Cause GC按钮,就会开始显示数据,如下图所示。

这时data object的Total Size为270.266KB。接下来操作应用,这个应用仍旧是在2.2小节所举的内存泄漏的例子,我反复的在MainActivity和SecondActivity跳转了10次(点击Button共20次),数据显示为: 

data object的Total Size变为了768.172KB。这时我点击Cause GC按钮,数据显示为:

可以看到data object的Total Size变为了444.516KB,再点击一次Cause GC按钮: 

Total Size变为了323.312KB,经过两次Cause GC的操作,Total Size的值从768.172KB变为了323.312KB,这是一个比较大的变化,说明在Cause GC操作之前有462.86KB(768.172KB-323.312KB)的内存没有被回收,可能发生了内存泄漏。


5. Memory Analyzer Tool 

1. 在 Android Studio 中先将 hprof 文件导出为 MAT 可以识别的 hprof 文件。

内存分析工具_第8张图片

2. 打开刚才导出的文件。

内存分析工具_第9张图片

经过分析后会显示如下,Leak Suspectss 是一个关于内存泄露猜想的饼图,Problem Suspect 1 是泄露猜想的描述。

内存分析工具_第10张图片

Overview 是一个概况图,把内存的消耗以饼状图形式显示出来,鼠标在每个饼块区域划过或者点击,就会在 Inspector 栏目显示这块区域的相关信息。 MAT 从多角度提供了内存分析,其中包括 Histogram、 Dominator Tree、 Leak Suspects 和 Top consumers 等。 
内存分析工具_第11张图片

这里使用 Histogram 进行分析,切换到 Histogram 页面。 这个页面主要有 4 个列,Class Name、 Objects、 Shallow Heap 和 Retained Heap。 其中 Class Name 是全类名,Objects 是这个类的对象实例个数。 Shallow Heap 是对象本身占用内存大小,非数组的常规对象,本身内存占用很小,所以这个对泄露分析作用不大。 Retained Heap 指当前对象大小和当前对象能直接或间接引用的对象大小的总和,这个栏目是分析重点。

内存分析工具_第12张图片

内存分析是分析的整个系统的内存泄露,而我们只要查找我们 App 的内存泄露情况。 这无疑增加了很多工作,不过幸亏 Histogram 支持正则表达式查找,在 Regex 中输入我们的包名进行过滤,直奔和我们 App 有关的内存泄露。

内存分析工具_第13张图片

过滤后就显示了 App 相关内存信息,按 Retained Heap 大小排列下,发现 MainActivity 和 TestActivity 这两个类问题比较大。 TestActivity 的问题更突出些,所以先从 TestActivity 下手。

首先看下是哪里的引用导致了 TestActivity 不能被 GC 回收。 右键使用 Merge Shortest Paths to GC Roots显示距 GC Root 最短路径,当然选择过程中要排除软引用和弱引用,因为这些标记的一般都是可以被回收的。

内存分析工具_第14张图片

进入结果页查看。

内存分析工具_第15张图片


6. LeakCanary 检查

项目地址:https://github.com/square/leakcanary

使用方式很简单,参考项目里面的介绍即可。

内存分析工具_第16张图片

你可能感兴趣的:(Android代码经验)