android内存泄漏分析

1.判断内存泄漏:

第一种方法:

as底下的标签里的android monitor(平时看log的地方)上面有个子标签monitors,切换到monitors,可以观察内存、cpu、网络等使用情况

反复进行某项操作,gc后(上面有个垃圾车图标,点击一下),观察内存占用是否稳定,如果每次进行这个操作,内存都增长,并且gc后不释放

说明这个操作存在内存泄漏

第二种方法:

打开ddms,在左侧选择设备中要观察的进程,点击上面的update heap按钮,在右边的heap标签页中,点击cause gc,反复操作app(可以反复操作疑似泄漏点),同时gc,

如果allocated的内存不断增长,data object的大小和数量不断增加,则存在内存泄漏

o    Heap Size 堆的大小,当资源增加,当前堆的空余空间不够时,系统会增加堆的大小,若超过上限 (例如64M,视平台和具体机型而定)则会被杀掉

o    Allocated 堆中已分配的大小,这是应用程序实际占用的内存大小,资源回收后,此项数据会变小





Heap视图中部有一个Type叫做dataobject,即数据对象,也就是我们的程序中大量存在的类类型的对象。在data object一行中有一列是“Total Size”,其值就是当前进程中所有Java数据对象的内存总量,一般情况下,这个值的大小决定了是否会有内存泄漏。可以这样判断:

a) 不断的操作当前应用,同时注意观察data object的Total Size值;
b) 正常情况下Total Size值都会稳定在一个有限的范围内,也就是说由于程序中的的代码良好,没有造成对象不被垃圾回收的情况,所以说虽然我们不断的操作会不断的生成很多对象,而在虚拟机不断的进行GC的过程中,这些对象都被回收了,内存占用量会会落到一个稳定的水平;
c) 反之如果代码中存在没有释放对象引用的情况,则dataobject的Total Size值在每次GC后不会有明显的回落,随着操作次数的增多Total Size的值会越来越大,
  直到到达一个上限后导致进程OOM被kill掉。


2.找到具体的内存泄漏点

使用as自带的dump分析功能:

1. 打开Android Device Monitor,操作如下图



2. 在Android Device Monitor界面中选在你要分析的应用程序的包名,点击Update Heap来更新统计信息,然后点击Cause GC即可查看当前堆的使用情况,点击Dump HPROF file,将该应用当前的内存信息保存成hprof文件,放在桌面即可,操作如下图



3. 用AndroidStudio打开刚刚保存的hprof文件,将文件直接拖进AndroidStudio中即可,选后选择Package Tree View,内存使用情况就是以包名分类



4. 在界面中找到你的应用程序的包名,打开即可看到内存的使用情况,自己写的类一目了然!如果有内存泄露,很容易看到。(列出的对象都是存在内存中没有释放的对象,分析其中是否存在泄漏,比如一个页面打开再关闭,本来应该释放,如果还存在内存中,就有可能是内存泄漏了)


也可以在底下的android monitor的 monitors的内存监控中直接生成hprof文件,生成后,as会自动打开


使用mat工具分析:

DDMS 可以将当前的内存 Dump成一个 hprof格式的文件,MAT 读取这个文件后会给出方便阅读的信息,配合它的查找,对比功能,就可以定位内存泄漏的原因。

·        获取 hprof文件 
点击工具栏上的  按钮,将内存信息保存成文件。 如果是用 MAT Eclipse 插件获取的 Dump文件,则不需要经过转换,Adt会自动进行转换然后打开。

·        转换 hprof文件 
DDMS Dump 出的文件要经过转换才能被 MAT识别,Android SDK提供了这个工具 hprof-conv (位于 sdk/tools下)

·    ./hprof-conv xxx-a.hprof xxx-b.hprof

·        用 MAT打开转换后的 hprof文件 

 

1.3  Histogram 查询

 

用的最多的功能是 Histogram,点击 Actions下的 Histogram项将得到 Histogram结果(注意mat工具不会一下子列出所有信息,双击最后一行的“Total:xxxxxxx”,会列出更多条目,但是条目太多,所以要用搜索功能):

它按类名将所有的实例对象列出来,可以点击表头进行排序,在表的第一行可以输入正则表达式来匹配结果 (注意区分大小写):

在某一项上右键打开菜单选择 list objects ->with incoming refs 将列出该类的实例:

ListObjects>with incoming references
表示的是 当前查看的对象,被外部应用


ListObjects>with outGoing references

表示的是 当前对象,引用了外部对象


测试:
A类,里面有一个B对象

在out里面看到了B, 而in里面没有看到B

它展示了对象间的引用关系(树形结构来表示引用的层级关系),比如展开后的第一个子项表示这个 HomePage(0x420ca5b0)被HomePageContainer(0x420c9e40)中的 mHomePage属性所引用.

快速找出某个实例没被释放的原因,可以右健 Path to GC Roots-->exclue all phantom/weak/soft etc. reference(软引用,弱引用可以被回收掉,不用会产生内存泄漏) :

得到的结果是:

从表中可以看出 PreferenceManager -> … ->HomePage这条线路就引用着这个 HomePage实例。用这个方法可以快速找到某个对象的 GC Root,一个存在 GC Root的对象是不会被 GC回收掉的.


3.MAT多文件比对

使用步骤

1.运行手机端程序,进入待测试内存状态页面

2.使用eclipse ddms 获取当前内存快照,并保存1.hprof文件

 

选择应用,点击箭头按钮

3.操作应用到功能页面并返回待测试页面(不要gc)重复2操作保存2.hprof文件

4.重复3保存3.hprof文件

5.命令行将Androidhprof转换成Javahprof文件(使用的android sdk Tools目录下的hprof工具)

命令:D:\lwh\Software\adt-bundle-windows-x86-20130219\sdk\tools\hprof-conv.exe eBest.mobile.android3.hprof 3.hprof

 

6.运行mat.exe打开3hprof文件

 

7.在histogram点击右键打开菜单添加到对比列表中

 

8.将3个文件的histogram添加到对比列表,然后点击感叹号对比

 

9出现分析页面

 

 

分析内存泄漏

1.objects列表表示个数,shallow heap表示堆内存

2.第一列表示java的数据类

3.Regex栏输入查找自定义类

 

4.通过分析哪一个类增加过快,就可以判断为该类没有释放,导致内存溢出


 ps:使用findbug可以静态检测代码例如流没关闭,游标未关闭等导致的内存溢出








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值