android内存优化之三内存分析工具的使用
来源:互联网 发布:成本估算软件 编辑:程序博客网 时间:2024/06/05 12:12
anroid内存分析工具的使用
一.Eclipse Heap分析内存泄露
Android开发中避免不了碰到内存泄露问题,这里先大概讲下内存泄露的基本概念:内存泄露官方的解释是是用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元,直到程序结束。它也可以理解为new的新对象用完后,该对象没有得到回收,造成的无用的对象一直占据着内存,这种无用的随着操作的次数越多,占据的内存越多,直到内存溢出程序,报错停止运行。内存溢出问题比起程序直接报错的问题更难定位,光靠阅读代码来分析内存溢出问题工作量也有些大,所以我们就不得不借助工具分析内存溢出问题。这一章节介绍的主要是如何使用内存分析工具MAT。我们用的最多的一般都是Eclipse自带的DDMS工具,进入DDMS后其界面如下:
这里先讲下该工具的使用步骤:
1. 通过USB线连接手机到PC上,android调试终端开启需要进行内存分析的APP,点击DDMS选项,进入堆显示界面。
2. 在Devices界面选择APP的进程名,如图所示我的APP进程名是com.example.oomtest。
3. 接着点击如上图所示的左上角绿色按钮UpdateHeap,用于更新显示APP的内存堆详情,点击后出现上图右边的Heap界面,即APP的堆的使用情况。其中Heap Size即APP的堆大小,是可变,至于上限是怎么设定的可以看下上一章节。Allocated即当前APP分配出去的堆大小,一般进行某个操作后是否内存泄露可以通过查看Allocated是否增大进行简单的判定,但是不一定准确,但是对于明显的内存泄露还是可以的,比如加载大图片并显示时。
4. 上图右边的Heap界面,有个Cause GC按钮是用于触发你的手机的GC线程进行内存回收。这里要提下的是一些人在监听某个界面的堆情况时,进入某个界面退出后根本没有点击Cause GC,此时发现退出界面后Allocated大小增大了,以为就是内存泄露了。其实不是的,只是有时GC线程自己还没扫描到你的APP,此时该APP的堆是还没有被回收的,所以Allocated的大小比之前的增加了。所以在进行某个操作后,要查看APP的堆情况还要点击Cause GC,建议多点击几次。
5 . 步骤5的Dump HPROF file按钮是用于下载heap内存分析的文件,接着要讲的分析工具讲用到该文件。
看到这里可能有些网友会问了,有些代码明明是内存泄露了,为什么Allocted还是显示正常的,即操作前和操作后,Allocted大小都没变化。是的,这里也是使用DDMS查看内存泄露的缺点,一些隐蔽性比较强的内存泄露,用DDMS是看不出来的。所以第二节要讲的是如何通过Memory Analyer工具进行内存泄露分析,该方法会准确很多,也方便问题的定位。
二. Memory Analyer Tools的Program supect分析内存泄露
这里要介绍的工具不是Eclipse自带的,所以需要下载Memory Analyer Tools(简称MAT,也可以作为插件集成到Eclipse中),本人是自己下载Memory Analyer工具。安装好Memory Analyer工具后,接着讲操作步骤:
1. 点击上图中的步骤5中的Dump HPROF file按钮下载堆分析文件,即后缀名为hprof的文件。
2. 由于下载的hprof文件在MAT中无法正常读入,所以需要sdk中的hprof-conv进行转换才可以在MAT正常读入。为了方便文件转换,接着进入sdk中查看hprof-conv工具放在什么位置,建议未转换前的hprof文件跟hprof-conv放在同一目录下,因为接着在cmd中进行转换时不用输入太长的文件路径。本人这里的hprof-conv工具的绝对路径为D:\ProgramFiles\eclipse\Android-sdk-windows-full\platform-tools>hprof-conv,同时也把转换前的hprof文件也放到这个位置。
3. 打开cmd,进入到hprof-conv所在的目录下,输入hprof-conv old.hprof new.hprof后按回车键,接着在D:\ProgramFiles\eclipse\Android-sdk-windows-full\platform-tools目录下生成的new.hprof文件,即为MAT可以读入的hprof文件。注:其中old.hprof为转换前的文件名,new.hprof为转换后的文件名。
4. 打开MAT,并导入转换后的hprof文件,操作如下图右上角所示:
5. 导入后的界面如下图所示,界面上的Problemsupect就是MAT帮你找出来的可能内存泄露的地方,看到这里你可能会想,这样很方便啊,MAT都帮你把所有可能内存泄露的地方都找出来了,接着点击Problem Supect一个一个慢慢看就可以了,其实网上很多贴也是这么说的。在这里我想说通过Problem Supect来定位某些内存泄露问题(比如加载大图片或者加载很多小图片的情况下)也是一种方法,但是此方法跟Eclipse的Heap来分析内存泄露一样,也是不准确的。
三 . 使用MAT准确有效的分析方法
下面重点介绍下另一种MAT分析内存泄露的方法,到这里你可能又会有疑问了:什么样的内存泄露是上面介绍的两个方法可能检测不出来的?这里也顺便说下吧。
(1). Activity的context被生命周期更长的对象(内部类和静态变量等)占据,导致的内存泄露问题。
(2). Cursor用完没有colse造成的内存泄露问题。
这里先介绍下几个基本概念,后面会用到: (1)Shallow Heap是对象本身占据的内存的大小,不包含其引用的对象。对于常规对象(非数组)的Shallow Size由其成员变量的数量和类型来定,而数组的ShallowSize由数组类型和数组长度来决定,它为数组元素大小的总和。(2)Retained Heap为当前对象大小+当前对象可直接或间接引用到的对象的大小总和。(间接引用的含义:A->B->C,C就是间接引用) ,并且排除被GC Roots直接或者间接引用的对象。
操作步骤:
(2).步骤2,如上图所示,点击Histogram选项,进入到Histogram界面,如下图所示。其中进程名输入框用于输入APP的进程名,从而可以查看APP的堆情况。
下面用一个内存泄露例子简单分析下,在Activity中定义一个线程内部类,并在线程中长时间休眠,该测试APP的进程名为com.example.oomtest,关键代码如下:
protectedvoid onCreate(BundlesavedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
Log.i(TAG,"onCreate");
setContentView(R.layout.activity_second);
new TestThread().start();
}
publicclass TestThreadextends Thread {
@Override
publicvoid run() {
super.run();
try {
Thread.sleep(1000 * 60 *1000);
}catch (InterruptedExceptione) {
e.printStackTrace();
}
}
}
进入测试界面并退出该界面操作一次,我们在获取hropf文件之后,转换并导入MAT中,打开Histogram界面后,在<Regex>中输入apk的进程名字,比如本程序使用的是com.example.oomtest,接着界面会列出APP的堆情况,如下图所示。
从上图中的Objects列中可以看出当退出测试界面SencondActivity时,它的实例存在。所以可以判定SencondActivity发生了内存泄露,但是使用前面介绍的两种方法根本就分析不出APP发生了内存泄露。到这里你可能也会问,知道了SencondActivity发生了内存泄露,那么怎么知道具体是哪里发生了内存泄露?这个也简单,这也是Histogram分析内存泄露问题的优势,操作步骤如下图所示。
- android内存优化之三内存分析工具的使用
- Android内存优化一:内存分析工具 MAT 的使用
- Android内存优化一:内存分析工具 MAT 的使用
- Android内存优化(三)-- 分析内存的使用
- Android内存优化详解以及内存分析工具MAT的使用
- 内存泄漏分析之-内存分析工具的使用
- Android内存优化之——static使用篇(使用MAT工具进行分析)
- Android内存优化之——static使用篇(使用MAT工具进行分析)
- android:MAT内存分析工具的使用
- android:MAT内存分析工具的使用
- android内存分析工具MAT的使用
- Android内存优化(二)-- 分析内存的使用
- Android内存优化(四)-- 分析内存的使用
- Android内存优化(五)-- 分析内存的使用
- Android内存优化工具(三)MAT
- Tomcat内存优化4.1 内存泄漏——内存分析工具 MAT 的使用
- android优化(2)--内存泄漏之工具使用
- Android内存优化的分析
- Spring配置文件中<context:annotation-config/>
- Something inside Qt (Day 1)
- python入门
- 数字之魅:寻找发帖“水王”
- 微信公众号添加自定义菜单
- android内存优化之三内存分析工具的使用
- Html对话框三种样式
- 不能将类模板的声明与实现分开写
- assert的作用是什么
- Android横竖屏切换总结
- Java并发 Thread、Executor、ForkJoin和Actor
- Qt多窗口切换程序
- 线性筛
- mac 反编译apk