内存分析工具

内存分析工具

1. Lint 

使用 Lint 代码静态检查

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


2. 选择 Lint 扫描区域。


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



2. Memory Monitor

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

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

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


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


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


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


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



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会显示出捕获快照的期间。

QQ截图20170708172907.png

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

2. alloc文件分析

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

QQ截图20170708174544.png

该alloc文件显示以下信息:

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


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

QQ截图20170708192205.png

可以选择列表中的一项,单击鼠标右键,在弹出的菜单中选择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按钮,就会开始显示数据,如下图所示。

QQ图片20170709204916.png

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

QQ截图20170709210450.png

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

QQ截图20170709212646.png

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

QQ截图20170709220441.png

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 文件。

这里写图片描述

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

这里写图片描述

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

这里写图片描述

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

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

这里写图片描述

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

这里写图片描述

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

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

这里写图片描述

进入结果页查看。

这里写图片描述


6. LeakCanary 检查

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

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

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值