Android应用程序内存分析
原文链接:http://android-developers.blogspot.com/2011/03/memory-analysis-for-android.html
Dalvik 自带有内存回收机制,但这并不意味程序员可以忽略内存的管理。在移动设备上,内存比较紧缺,因此你应当对内存的使用更加小心。在本文中,我们将介绍如何使用android SDK中的内存分析工具来对应用程序的内存使用情况进行分析。
有些内存问题是显而易见的。例如,如果应用程序在每次用户触摸屏幕时都会泄漏一些内存,那么该应用将很快因为 OutOfMemoryError的异常而崩溃。另外一些则更加隐蔽,它们有可能只会导致应用程序和整个系统变慢(垃圾回收器频繁和长时间进行垃圾回收)
调试工具
在android SDK中提供了两种内存分析的方法:内存申请跟踪(以下用Allocation tracker) 和 堆转储(以下用heap dump)。Allocation tracker可以帮我们了解到一段时间内,应用对内存的申请情况,但是它不能提供任何有关应用程序堆的信息。更多有关内存申请追踪的信息请看 Tracking Memory Allocations 。接下来的篇幅中我们将重点关注一种更加强有力的分析工具——heap dump的使用。
Heap dump是应用程序堆的的快照,它存放在一种特定格式(HPROF)的二进制文件中。Dalvik使用类似于HPROF的格式来保存heap dump。生成应用程序的heap dump的方法有多种,DDMS中的head dump按钮就提供了生成heap dump的功能。如果想要对heap dump的生成有更加精细的控制,可以在程序中使用android.os.Debug.dumpHprofData()来生成。
常用的分析heap dump的工具有jhat 和 Eclipse Memory Analyzer (MAT) 。在分析之前,我们需要将Dalivk heap dump文件的格式转换成J2SE 标准的HPROF格式。android SDK中提供了hprof-conv工具来进行这个转换。命令如下:
hprof-conv dump.hprof converted-dump.hprof
例子:如何分析内存泄漏
在Dalivk环境中,程序员不能显式的申请和释放内存,因此内存不会像在C/C++中的那样真正泄漏。在这种情况下,内存泄漏往往指的是程序中保存了无用的对象的引用,有时保存一个对象的引用,而这个对象又拥有大量其他对象的引用,那么这些对象将都无法被垃圾回收器回收。
让我们看android SDK中的一个示例程序Honeycomb Gallery sample app。这是一个用来展示如何使用android Honeycomb 中的新API的照片库应用(如何下载和编译这个应用的代码,请看介绍)。我们将小心的在这个应用的代码中加入一个内存泄漏的bug,以讲述如何调试这样的问题。
假如我们想修改这个应用,让其具有从网络上下载图片的能力。为了提升体验,我们决定实现一个缓存以存储最近收到的图片,我们通过对ContentFragment.java文件进行一些小的修改来实现这个想法。首先在这个类的顶部加上一个静态的变量
private static HashMap sBitmapCache = new HashMap();
这个变量将保存我们想要缓存的图片,现在我们修改updateContentAndRecycleBitmap() 加入检查存储和存入缓存的功能
void updateContentAndRecycleBitmap(int category, int position) {
if (mCurrentActionMode != null) {
mCurrentActionMode.finish();
}
// Get the bitmap that needs to be drawn and update the ImageView.
// Check if the Bitmap is already in the cache
String bitmapId = "" + category + "." + position;
mBitmap = sBitmapCache.get(bitmapId);
if (mBitmap == null) {
// It's not in the cache, so load the Bitmap and add it to the cache.
// DANGER! We add items to this cache without ever removing any.
mBitmap = Directory.getCategory(category).getEntry(position)
.getBitmap(getResources());
sBitmapCache.put(bitmapId, mBitmap);
}
((ImageView) getView().findViewById(R.id.image)).setImageBitmap(mBitmap);
}
使用DDMS来分析内存使用情况
DDMS是android最主要的一个调试工具,它是ADT插件的一部分,同时在android SDK的tools/ directory目录下也有一个独立的版本。更对关于DDMS的信息,请看Using DDMS
让我们使用DDMS来分析内存使用情况。DDMS有两种启动方式: