android内存优化之三内存分析工具的使用

 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的load heap按钮是用于下载heap内存分析的文件,接着要讲的分析工具需要用到该文件。

看到这里可能有些网友会问了,有些代码明明是内存泄露了,为什么Allocted还是显示正常的,即操作前和操作后,Allocted大小都没变化。是的,这里也是使用DDMS查看内存泄露的缺点,一些隐蔽性的内存泄露,用DDMS是看不出来的。所以第二节要讲的是通过Memory Analyer工具进行内存泄露分析,这样会准确很多,也很方便问题的定位。

二. Memory Analyer Tools的Program supect分析内存泄露

先讲下这个工具不是Eclipse自带的,所以需要自己下载Memory Analyer Tools(简称MAT,也可以作为插件集成到Eclipse中),本人是自己下载Memory Analyer工具。安装好Memory Analyer工具后,接着讲操作步骤:

1.  点击上图中的步骤5中的load heap按钮下载堆分析文件,即后缀名为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直接或者间接引用的对象

操作步骤:

(1).步骤1,点击Overview选项,进入到主界面

(2).步骤2,点击Histogram选项,进入到Histogram界面,如下图所示。其中进程名输入框用于输入APP的进程名,从而可以查看APP的堆情况。

下面用一个内存泄露例子简单分析下,方便网友入门。在Activity中定义一个线程内部类,并在线程中长时间休眠,该测试APP的进程名为com.example.oomtest,关键代码如下:

protectedvoid onCreate(Bundle
savedInstanceState) {

// TODO Auto-generated method stub

super.onCreate(savedInstanceState);

Log.i(TAG,
"onCreate");

setContentView(R.layout.activity_second);

new TestThread().start();

}

publicclass TestThread
extends Thread {

@Override

publicvoid run() {

super.run();

try {

Thread.sleep(1000 * 60 *1000);

} catch (InterruptedException
e) {

e.printStackTrace();

}

}

}

进入测试界面并退出该界面操作一次,我们在获取hropf文件并转换导入MAT中,打开Histogram界面后,在<Regex>中输入apk的进程名字,比如本程序使用的是com.example.oomtest,接着界面会列出APP的堆情况,如下图所示。

从上图中的Objects列中可以看出当退出测试界面SencondActivity时,它的实例存在。所以可以判定SencondActivity发生了内存泄露,但是使用前面介绍的两种方法根本就分析不出APP发生了内存泄露。到这里你可能也会问,知道了SencondActivity发生了内存泄露,那么要怎么知道具体哪里发生了内存泄露呢?这个也简答,这就是通过Histogram进行分析内存泄露的优势了,操作步骤如下图所示:

跟着上图所示操作,接着出现以下界面,从下图中可以看出activity实例没有被回收,这就是前面所说的隐藏性比较强的内存泄漏类型1了,主要原因就是Activity中的线程一直占住了Activity的this造成的内存泄露,所以当该Activity被Destroy时,Activity的实例没法被GC回收。

现将线程的休眠时间修改为100时,按同样的操作方法测试,SencondActivity的子线程由于休眠时间比较短,此时当Activity被Destroy时,Activity的this已经被释放了,所以不会发生内存泄露的情况,其堆内存情况如图所示:

从列表中可以看出此时SencondACtity的Object(对象)为0,即SencondActivity没有存在对象,所以用该方法进行内存泄露分析是很准确的,但是同样的程序通过前面的两种方法就无法定位出哪里出问题,甚至检测不出内存泄露了。这一章就先介绍到这里吧,下一章节将介绍其他一些隐藏性比较强的内存泄露问题,以便各大网友开发出高质量的APP。

时间: 2024-11-10 07:00:24

android内存优化之三内存分析工具的使用的相关文章

Android 性能优化 五 性能分析工具dumpsys的使用

Android提供的dumpsys工具可以用于查看感兴趣的系统服务信息与状态,手机连接电脑后可以直接命令行执行adb shell dumpsys 查看所有支持的Service但是这样输出的太多,可以通过dumpsys | grep "DUMP OF SERVICE" 仅显示主要的Service的信息 一.列出dumpsys所有支持命令 > adb shell $ dumpsys | grep "DUMP OF SERVICE" 以下是在我个人三星S3手机上的输

Android 性能优化之内存泄漏检测以及内存优化(上)

在 Java 中,内存的分配是由程序完成的,而内存的释放则是由 Garbage Collecation(GC) 完成的,Java/Android 程序员不用像 C/C++ 程序员一样手动调用相关函数来管理内存的分配和释放,虽然方便了很多,但是这也就造成了内存泄漏的可能性,所以记录一下针对 Android 应用的内存泄漏的检测,处理和优化的相关内容,上篇主要会分析 Java/Android 的内存分配以及 GC 的详细分析,中篇会阐述 Android 内存泄漏的检测和内存泄漏的常见产生情景,下篇会

[Android 性能优化系列]内存之终极篇--降低你的内存消耗

大家如果喜欢我的博客,请关注一下我的微博,请点击这里(http://weibo.com/kifile),谢谢 转载请标明出处(http://blog.csdn.net/kifile),再次感谢 原文地址:http://developer.android.com/training/articles/memory.html 在接下来的一段时间里,我会每天翻译一部分关于性能提升的Android官方文档给大家 建议大家在看本文之前先去我的博客看看 [Android 性能优化系列]内存之基础篇--Andr

[Android 性能优化系列]内存之基础篇--Android怎样管理内存

大家假设喜欢我的博客,请关注一下我的微博,请点击这里(http://weibo.com/kifile),谢谢 转载请标明出处(http://blog.csdn.net/kifile),再次感谢 原文地址:http://developer.android.com/training/articles/memory.html 在接下来的一段时间里,我会每天翻译一部分关于性能提升的Android官方文档给大家 以下是本次的正文: ################ 随机訪问存储器(Ram) 无论在哪种软件

Android内存优化9 内存检测工具3 MAT比Menmery Monitor更强大

在Android性能优化第(一)篇---基本概念中讲了JAVA的四大引用,讲了一下GCRoot,第二篇Memory Monitor检测内存泄露仅仅说了Menmery Monitor的使用,这篇博客谈一下MAT来寻找内存泄露,相对来说,Memory Monitor没有MAT强大,但是在开始介绍MAT之前,上两篇没有说清楚的问题先说一下. GC回收对可回收对象的判定什么样的对象是可以被回收的?当然是GC发现通过任何referencechain(引用链)无法访问某个对象的时候,该对象即被回收.名词GC

Android性能优化(四):内存优化

1.内存的分配策略概述 程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的,对应的,三种存储策略使用的内存空间主要分别是静态存储区(也称方法区).堆区和栈区. 静态存储区(方法区):内存在程序编译的时候就已经分配好,这块内存在程序整个运行期间都存在.它主要存放静态数据.全局static数据和常量. 栈区:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放.栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限. 堆区:亦称动态

Android性能优化之内存篇

http://www.cnblogs.com/flyme2012/p/dd1b11a4ea151458d77411f5e99bc0dc.html 下面是内存篇章的学习笔记,部分内容与前面的性能优化典范有重合,欢迎大家一起学习交流! 1)Memory, GC, and Performance 众所周知,与C/C++需要通过手动编码来申请以及释放内存有所不同,Java拥有GC的机制.Android系统里面有一个Generational Heap Memory的 模型,系统会根据内存中不同的内存数据类

Android应用优化之内存概念

导语 现在的Android智能手机发展信息万变,从一开始的HTC到小米价格战到现在高端市场份额战,在软硬件都发生了翻天覆地的变化.在硬件上内存从一开始的一两百M到现在4G.从软件上我们从一开始为了实现需求而写代码到现在为了代码更健壮.更漂亮而进行不断优化代码.这些都是Android发展的必然一步.今天我来跟大家一起分享Android内存优化的相关概念和实践. 概念 进程内存与RAM之间的关系 进程内存既是虚拟内存(或者叫逻辑内存),而程序的运行需要实实在在的内存,即物理内存(RAM),在需要的时

Android 如何优化APP内存

极力推荐Android 开发大总结文章:欢迎收藏 程序员Android 力荐 ,Android 开发者需要的必备技能 随机存取存储器(RAM)在任何软件开发环境中都是非常有价值的资源,但对于物理内存经常受到限制的移动操作系统来说,它更有价值. 尽管Android运行时(ART)和Dalvik虚拟机都执行常规垃圾收集,但这并不意味着您可以忽略应用程序分配和释放内存的时间和位置. 您仍然需要避免引入内存泄漏,通常由静态成员变量中的对象引用引起,并在生命周期回调定义的适当时间释放任何引用对象. 本页面