原创android内存管理-hprof文件

欠伸展肢体,吟咏心自愉。这篇文章主要讲述原创android内存管理-hprof文件相关的知识,希望能为你提供帮助。
转载请注明出处  http://www.cnblogs.com/weiwangnuanyang/p/5703702.html 
如果只是想确定一下某一个场景是否有内存泄漏,androidStadio的控制台就有一个好工具,反复操作观察曲线是否上扬,如果曲线上扬则说明内存泄漏

原创android内存管理-hprof文件

文章图片

 
点击旁边第三个按钮也可以生成hprof文件。不过本人比较习惯用Eclipse,这里就以Eclipse为例啦。
下面就来重点介绍一下如何利用Memory Analysis(Eclipse的一个插件,具体安装方式请移步度娘)   生成   和   分析   hprof文件。
1. 生成hprof文件。
生成hprof文件很简单,在Eclipse的DDMS视图内,点击你需要调试的进程,然后点击[DUMP HPROF FILE]按钮就好啦。
       
原创android内存管理-hprof文件

文章图片

对于内存泄漏问题一般是需要对比分析的,所以如果没有自动化测试环境的话,手动测试可以在进入app时存一个hprof文件,
然后开始反复测试泄漏的场景20+次,存一个hprof文件,再反复操作20+次,再存一个hprof文件。
2. 简单介绍。
下面是打开一个hprof文件后的概览视图。
原创android内存管理-hprof文件

文章图片

从此概览视图中我们可以以此看到
Details(细节):展示了总大小,classes大小,objects大小, classloader 数量;unreachable objects histogram(可被回收对象柱状图);
 
Biggest Objects by Retained Size(占用内存最大对象饼状图);
 
Histrogram(柱状图):列举每个类的对象个数;
Dominator Tree(支配树): 列举最大的对象,和因为类而引起的不能回收的对象占用空间大小;
Top Consumers(最大的消费者): 列举占用内存最大的对象的饼图;
Duplicate Classes:检测由多个类加载器加载的类;
 
Leak Suspects:包括一个简单的泄漏分析和一个系统概述;
Top Components: 列举在堆中大小大于总大小1%的组件,以class loader 分类(system class loader,PathClassLoader,DexClassLoader);
 
Component Report: 分析属于common root package 或者 class loader的对象。
 
面板上面还有一些按钮提供了根据地址搜对象,查看线程详细信息,生成报表等功能。具体的大家点点看看就ok了。
 
3. 分析hprof文件实战。
以本人有限的分析内存泄漏的经验来看,Memory Analysis提供的Leak Suspects往往都是不准确的,它的分析是基于类的对象在内存中占用的总大小,
总是把一些系统类比如byte列举在第一位。就像下面这样。
       
原创android内存管理-hprof文件

文章图片

 
  所以真正的有效分析还得靠自己。
要解决java内存泄漏的问题,首先要了解java中哪些情况会造成内存泄漏,具体请移步   http://www.cnblogs.com/weiwangnuanyang/p/5704596.html  ;
分析内存问题,一个非常有效的方法就是对比开始测试和结束测试时的类的个数。然后再分析这些类的引用关系。
下面就以一个实例来说一下。
第一步:生成两个文件并打开,如下有17:55:55和18:00:29的两份文件。
原创android内存管理-hprof文件

文章图片

 
  第二步:打开第二个文件的类柱状图。
 
原创android内存管理-hprof文件

文章图片
   
打开以后是这样的:
 
原创android内存管理-hprof文件

文章图片

  第三步:点击Histogram上面的对比按钮,与另一份文件做对比。
     
原创android内存管理-hprof文件

文章图片

  这时候得到的结果是这样的:
原创android内存管理-hprof文件

文章图片

    第四步:在< Regex> 的输入框里输入你的包名关键字,筛选出你自己的类,过滤掉系统类。
这时候那些类泄漏了就非常明晰了。反复操作n次就增加了n+个的类多半都是有问题的。
 
原创android内存管理-hprof文件

文章图片

第五部:分析这些类的引用关系。在这个对比表里点击右键是没有效果的,你需要打开一个新的Histogram视图,同样用你的包名筛选出你写的类。
然后选中一个点击右键,这时候会出来一个菜单,菜单中前三项分别表示对象的引用关系,类的引用关系,类的回收路径。
原创android内存管理-hprof文件

文章图片

 
  我们选择类的Merge Shortest Path to GC Root(最短回收路径)来看一下,点开以后的结果是这样的:
 
 
原创android内存管理-hprof文件

文章图片

首先可以看到有一大片InnerReceiver,这个肯定是有问题的,点开其中一个可以看到最后一个我们自己的类是BNavigator,点开这个类可以看到它注册了
【原创android内存管理-hprof文件】广播但是没有反注册。
 
原创android内存管理-hprof文件

文章图片

然后再看一下其他没有回收的对象,下面这个是因为MapController引用了CarNaviAcitity的Context,而MapController是一个Map的key.
这里有两个问题需要考虑,其一是MapController作为key是否是合适的,当它作为key时是否在无用时及时从Map中移出;其二是MapController引用了CarNaviActivity的
Context,而不是ApplicationContext,这是造成anroid的Activity泄漏的一个主要原因。
原创android内存管理-hprof文件

文章图片

 
  再来看SurfaceView也是引了Activity的Context.
 
原创android内存管理-hprof文件

文章图片

 
对于其他类的分析类似,在此不一一列举了。
 

    推荐阅读