Dalvik虚拟机支持垃圾收集,但是这不意味着你可以不用关心内存管理。你应该格外注意移动设备的内存使用,在上面内存空间是受到限制的。在这篇 文章里面,我们来看看Android SDK里面的一些内存剖析工具(profiling tools)是如何帮助我们修整应用程序的内存使用。
一些内存使用问题是很明显的,例如,如果在每次用户触摸屏幕的时候应用程序有内存泄露,将会有可能触发OutOfMemoryError,最终程序崩溃。另外一些问题却很微妙,也许只是降低应用程序和整个系统的性能(当高频率和长时间地运行垃圾收集器的时候)。
必要的工具:
Android SDK提供了2个主要的剖析应用程序内存使用情况的工具:DDMS里的一个分页Allocation Tracker和heap dumps。Allocation Tracker是很有用的,特别是当你想得到程序在一定的时间里内存的分配情况的一种感性认识的时候。但是它不能给你任何关于程序heap总体情况的任何 信息。关于Allocation Tracker的更多信息,请看文章Tracking Memory Allocations 。文章剩下的内容将把重点放在heap dumps,它是更强大的内存分析工具。
一个heap dump就是一个程序heap的快照,它保存为一种叫做HPROF的二进制格式。Dalvik用的也是类似的格式,但是不完全一样。这里是Java的HPROF工具 。有很多方法去生成一个运行时应用程序的heap dump。其中一种就是使用在DDMS里边的Dump HPROF file按钮。如果想产生更精确的dump数据,可以在程序中使用android.os.Debug.dumpHprofData() 方法。
分析heap dump,你可以使用一些标准的工具比如jhat 或者Eclipse Memory Analyzer(MAT) 。不过,首先你需要把.hprof文件从Dalvik格式转换成J2SE HPROF格式。你可以使用Android SDK提供的hprof-conv工具。例如:
- hprof-conv dump.hprof converted-dump.hprof
调试一个内存泄露实例:
在Dalvik运行时里边,程序员不能显式地分配和释放内存,所以这里的内存泄露跟c和c++里面的不同。在你的代码里边,内存泄露就是你保留了一个并不再需要的类对象的引用。有时候仅仅一个引用就会阻碍gc对一大堆对象的回收。
我们来过一个实际的例子,Android SDK里面提供的范例程序Honeycomb Gallery sample app 。它是一个photo gallery程序,用来演示一些新的Honeycomb API的使用。(下载和编译这些代码,请看这些命令 。)我们会有意地加入一个内存泄露在程序里边,然后来演示如何调试它。
想象一下我们想修改程序让它从网络下载图片。为了让它更具备灵活性,我们可以考虑实现一个缓存,保存最近查看过的图片。我们可以对ContentFragment.java做一些小的修改来达到这个目的。在class顶部,我们增加一个新的静态变量:
- private static HashMap<String,Bitmap> sBitmapCache = new HashMap<String,Bitmap>();
这里就是我们保存缓存的地方。现在我们可以修改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里检查heap的使用情况
Dalvik Debug Monitor Server(DDMS)是主要的Android调试工具之一,也是ADT Eclipse plug-in 的一部分,独立的程序版本也可以在Android SDK的根目录下的tools/下面找到。关于DDMS更多的信息,请参考使用DDMS 。
我们来使用DDMS检查这个应用的heap使用情况。你可以使用下面的两种方法启动DDMS:
- from Eclipse: click Window > Open Perspective > Other... > DDMS
- or from the command line: run
ddms
(or./ddms
on Mac/Linux) in thetools/
directory
在左边的面板选择进程com.example.android.hcgallery,然后在 工具条上边点击Show heap updates按钮。这个时候切换到DDMS的VM Heap分页。它会显示每次gc后heap内存的一些基本数据。要看第一次gc后的数据内容,点击Cause GC按钮:
我们可以看到现在的值(Allocated列)是有一些超过8MB。现在滑动相片,这时看到 数据在增大。因为只有仅仅13个相片在程序里边,所以泄露的内存只有这么大。在某种程度上来说,这时最坏的一种内存泄露,因为我们没法得到 OutOfMemoryError来提醒我们说现在内存溢出了。
生成heap dump
我们现在使用heap dump来追踪这个问题。点击DDMS工具条上面的Dump HPROF文件按钮,选择文件存储位置,然后在运行hprof-conv。在这个例子里我们使用独立的MAT版本(版本1.0.1),从MAT站点下载 。
如果你使用ADT(它包含DDMS的插件)同时也在eclipse里面安装了MAT,点击“dump HPROF”按钮将会自动地做转换(用hprof-conv)同时会在eclipse里面打开转换后的hprof文件(它其实用MAT打开)。
用MAT分析heap dumps
启动MAT然后加载刚才我们生成的HPROF文件。MAT是一个强大的工具,讲述它所有的特性超出了本文的范围,所以我只想演示一种你可以用来检测 泄露的方法:直方图(Histogram)视图。它显示了一个可以排序的类实例的列表,内容包括:shallow heap(所有实例的内存使用总和),或者retained heap(所有类实例被分配的内存总和,里面也包括他们所有引用的对象)。
如果我们按照shallow heap排序,我们可以看到byte[]实例在顶端。自从Android3.0(Honeycomb),Bitmap的像素数据被存储在byte数组里 (之前是被存储在Dalvik的heap里),所以基于这个对象的大小来判断,不用说它一定是我们泄露掉的bitmap。
右击byte[]类然后选择List Objects > with incoming references。它会生成一个heap上的所有byte数组的列表,在列表里,我们可以按照Shallow Heap的使用情况来排序。
选择并展开一个比较大的对象,它将展示从根到这个对象的路径--就是一条保证对象有效的链条。注意看,这个就是我们的bitmap缓存!
MAT不会明确告诉我们这就是泄露,因为它也不知道这个东西是不是程序还需要的,只有程序员知道。在这个案例里面,缓存使用的大量的内存会影响到后面的应用程序,所以我们可以考虑限制缓存的大小。
使用MAT比较heap dumps
调试内存泄露时,有时候适时比较2个地方的heap状态是很有用的。这时你就需要生成2个单独的HPROF文件(不要忘了转换格式)。下面是一些关于如何在MAT里比较2个heap dumps的内容(有一点复杂):
- 第一个HPROF 文件(using File > Open Heap Dump ).
- 打开 Histogram view.
- 在Navigation History view里 (如果看不到就从Window > Navigation History找 ), 右击histogram 然后选择Add to Compare Basket .
- 打开第二个HPROF 文件然后重做步骤2和3.
- 切换到Compare Basket view, 然后点击Compare the Results (视图右上角的红色"!"图标)。
相关推荐
在Android应用开发中,内存管理是一项至关重要的任务,因为它直接影响到应用的性能、稳定性和用户体验。内存监控工具能够帮助开发者检测和分析应用的内存使用情况,预防和解决内存泄漏等问题。"Emmagee.apk"可能是一...
基于静态分析方法的Android应用内存泄漏检测模型 Android 应用程序的内存泄漏问题较为常见,主要是由于部分开发人员对 Android 内存管理机制理解模糊所致。为了解决内存泄漏的检测问题,首先需要分析 Android 系统...
MAT工具不仅适用于Android应用,也适用于任何基于Java的系统。 **一、MAT的下载与安装** 由于MAT不是Android Studio的标准组件,开发者需要单独下载。通常,MAT会作为一个独立的Eclipse插件形式存在。在下载过程中...
在Android应用开发中,内存泄漏是一个严重的问题,它可能导致应用性能下降、响应变慢甚至崩溃。Android Studio作为官方推荐的集成开发环境(IDE),提供了强大的内存泄漏检测工具,帮助开发者定位并解决这些问题。...
标题中提到的是关于“Android应用程序内存泄漏的分析”,这意味着文档的核心内容将集中在分析Android平台下应用程序可能遇到的内存泄漏问题。内存泄漏是Android开发中非常常见且棘手的问题,它发生在一个对象不再被...
### Android应用内存占用测试 #### 一、内存占用的重要性 对于Android应用而言,优化内存占用是非常重要的。因为智能手机的RAM(随机访问存储器)资源是有限的,这意味着单个应用程序的内存占用越小,手机就能运行...
在Android系统中,内存分析是调试和优化应用性能的关键步骤。M8 android dump内存工具是一个专为M8设备设计的工具,它可以帮助...了解并熟练掌握这个工具的使用,对于提升Android应用的性能和稳定性具有重要意义。
### Android应用内存泄露详解 #### 一、内存泄露定义与理解 在Android开发过程中,内存泄露是一个常见的问题,尤其对于大型复杂的应用来说更是如此。内存泄露不仅会导致应用运行缓慢,严重时还会引起应用崩溃,极大...
4. **Debug.MemoryInfo**: 对于更深入的内存分析,可以使用`Debug`类的静态方法`getMemoryInfo()`,它返回一个`Debug.MemoryInfo`对象,包含了Dalvik/ART堆、Native堆、 ashmem和图形内存等的详细信息。 5. **Linux...
在Android里,程序内存被分为2部分:native和dalvik,dalvik就是我们普通的Java使用内存,分析堆栈的时候使用的内存。我们创建的对象是在这里面分配的,对于内存的限制是 native+dalvik 不能超过最大限制. Android ...
实验结果显示,在相同条件下,应用内存使用量降低了约30%,图片加载速度提高了20%以上,且未出现明显的图片质量下降。 #### 结论 综上所述,OOMS方案通过优化图片加载流程、动态内存管理和智能压缩算法,有效解决...
在ExmLeak这个压缩包文件中,你可以找到具体的代码实现,通过分析和实践这些例子,你将更好地理解和掌握如何避免Android应用中的内存泄漏问题。记住,良好的内存管理是提升应用性能和稳定性的重要因素。
Android系统的内存分析也涉及到进程和线程的理解。每个应用都有自己的Dalvik或ART堆,而线程共享这个堆。如果一个线程创建了大量的对象但没有释放,可能会导致该线程所在的应用进程内存占用过高。因此,合理管理线程...
总结来说,Android手机内存的分配涉及到硬件接口、内核、用户空间等多个层次,理解这些内存区域的划分和使用对于开发和调试Android应用程序、优化系统性能具有重要意义。同时,掌握查看和分析内存使用状态的工具和...
Android开发是一个庞大且复杂的领域,涵盖了许多不同的技术和工具,但本书将带你逐步走进这个领域,从基础知识到高级实践,全方位地解析Android应用的构建过程。 首先,书中会介绍Android开发环境的搭建,包括安装...
本文将详细介绍如何使用 MAT 分析 Android 应用程序中的内存泄露,特别是如何根据 heap dump 分析泄漏根源。 ClassLoader 和 Java 类加载机制 在介绍 MAT 之前,需要了解 Java 类加载机制。ClassLoader 是 Java 中...
在Android开发过程中,了解应用的内存使用情况是优化性能的关键步骤。内存分析工具可以帮助开发者检测内存泄漏、...综上所述,理解和熟练使用Android内存分析工具是提升应用质量的重要手段,需要开发者不断学习和实践。
4. **内存分析工具** - **Android Studio Profiler**:提供实时内存监控,可以查看内存分配、内存泄漏检测等功能。 - **MAT (Memory Analyzer Tool)**:Eclipse插件,用于分析Hprof文件,找出内存泄漏。 - **...
Android应用程序主要使用Java语言编写,因此其内存机制与Java内存管理有密切关系。本篇将详细探讨Android内存分析,包括内存分配、垃圾回收、内存溢出以及如何避免内存泄露。 1. **Android内存机制** Android程序...
以下是一些关于如何优化Android应用内存使用的关键知识点: 1. **了解内存限制**: Android系统对每个应用分配一定的内存空间,这个值在不同设备上会有所不同。了解目标设备的内存规格有助于设定合理的内存管理...