当前位置:文档之家› Android开发内存泄漏及检查工具使用培训资料

Android开发内存泄漏及检查工具使用培训资料

Android 开发内存泄漏及检查工具使用培训资料目录1内存泄露 (3)1.1 内存泄露的概念 (3)1.2 开发人员注意事项 (4)1.3 Android(java)中常见的引起内存泄露的代码示例 (4)1.3.1查询数据库没有关闭游标 (6)1.3.2 构造Adapter时,没有使用缓存的convertView (6)1.3.3 Bitmap对象不在使用时调用recycle()释放内存 (7)1.3.4 释放对象的引用 (8)1.3.5 其他 (9)2内存泄露的分析工具 (9)2.1 内存监测工具DDMS --> Heap (9)2.2 内存分析工具MAT (Memory Analyzer Tool) (10)2.2.1 生成.hprof文件 (10)2.2.2 使用MA T导入.hprof文件 (11)2.2.3 使用MA T的视图工具分析内存 (12)1内存泄露Android 应用程序开发以Java语言为主,而Java编程中一个非常重要但却经常被忽视的问题就是内存使用的问题。

Java的垃圾回收机制(Garbage Collection 以下简称GC)使得很多开发者并不关心内存使用的生命周期,只顾着申请内存,却不手动释放废弃的内存,而造成内存泄露,引起很多问题,甚至程序崩溃。

Android的虚拟机Dalvik VM和java虚拟机JVM没有什么太大的区别,只是在字节码上稍做优化,所以Android应用开发中同样会出现内存泄露的问题。

而且由于Android智能平台主要用于嵌入式产品开发,可用的内存资源更加稀少,所以对于我们Android应用开发人员来说,就更该了解Android程序的内存管理机制,避免内存泄露的发生。

1.1 内存泄露的概念在计算机科学中,内存泄漏(memory leak)指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况。

内存泄漏并非指内存在物理上的消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费。

内存泄漏与许多其他问题有着相似的症状,并且通常情况下只能由那些可以获得程序源代码的程序员才可以分析出来。

然而,有不少人习惯于把任何不需要的内存使用的增加描述为内存泄漏,严格意义上来说这是不准确的。

一般我们常说的内存泄漏是指堆内存的泄漏。

堆内存是指程序从堆中分配的,大小任意的(内存块的大小可以在程序运行期决定),使用完后必须显式释放的内存。

应用程序一般使用malloc,calloc,realloc,new等函数从堆中分配到一块内存,使用完后,程序必须负责相应的调用free或delete释放该内存块,否则,这块内存就不能被再次使用,我们就说这块内存泄漏了。

这里我们只简单的理解,在java程序中,如果已经不再使用一个对象,但是仍然有引用指向它,GC就无法收回它,当然该对象占用的内存就无法再被使用,这就造成内存泄露。

可能一个实例对象的内存泄露很小,并不会引起很大的问题。

但是如果程序反复做此操作或者长期运行,造成内存不断泄露,终究会使程序无内存可用,只好被系统kill掉。

在以下情况,内存泄漏导致较严重的后果:* 程序运行后置之不理,并且随着时间的流失消耗越来越多的内存(比如服务器上的后台任务,尤其是嵌入式系统中的后台任务,这些任务可能被运行后很多年内都置之不理);* 新的内存被频繁地分配,比如当显示电脑游戏或动画视频画面时;* 程序能够请求未被释放的内存(比如共享内存),甚至是在程序终止的时候;* 泄漏在操作系统内部发生;* 泄漏在系统关键驱动中发生;* 内存非常有限,比如在嵌入式系统或便携设备中;* 当运行于一个终止时内存并不自动释放的操作系统(比如AmigaOS)之上,而且一旦丢失只能通过重启来恢复。

1.2 开发人员注意事项对于开发者,对待内存泄露应该以防为主,以治为辅,因为一旦造成内存泄露,追查原因并不容易,虽然有工具可以利用,但是还是会耗费不必要的时间和精力来分析内存使用报告和反复搜查代码。

为了开发高性能和高质量的软件,防止出现豆腐渣工程的出现,我们要知道什么时候用gc什么时候用recycle以及到底用不用finalization,因为Java 对内存的分配只需要new开发者不需要显示的释放内存,但是这样造成的内存泄露问题的几率反而更高。

我们还需要:1.了解Java 的四种引用方式,比如强引用,软引用,弱引用以及虚引用。

一些复杂些的程序在长期运行很可能出现类似OutOfMemoryError 的异常。

2.并不要过多的指望gc,不用的对象可以显示的设置为空,比如obj=null,这里提示大家,java的gc使用的是一个有向图,判断一个对象是否有效看的是其他的对象能到达这个对象的顶点,有向图的相对于链表、二叉树来说开销是可想而知。

3.Android 为每个程序分配的对内存可以通过Runtime类的totalMemory() freeM emory() 两个方法获取VM的一些内存信息,对于系统heap内存获取,可以通过Da lvik.VMRuntime 类的getMinimumHeapSize()方法获取最小可用堆内存,同时显示释放软引用可以调用该类的gcSoftReferences()方法,获取更多的运行内存。

4.对于多线程的处理,如果并发的线程很多,同时有频繁的创建和释放,可以通过concurrent类的线程池解决线程创建的效率瓶颈。

5.不要在循环中创建过多的本地变量。

Java中的引用简介:在Java中内存管理,引用分为四大类,强引用HardReference、弱引用WeakReference、软引用SoftReference 和虚引用PhantomReference。

它们的区别也很明显,HardReference 对象是即使虚拟机内存吃紧抛出OOM 也不会导致这一引用的对象被回收,而WeakReference等更适合于一些数量不多,但体积稍微庞大的对象,在这四个引用中,它是最容易被垃圾回收的,而我们对于显示类似Android Market 中每个应用的AppIcon时可以考虑使用SoftReference来解决内存不至于快速回收,同时当内存短缺面临JavaVM崩溃抛出OOM前时,软引用将会强制回收内存,最后的虚引用一般没有实际意义,仅仅观察GC 的活动状态,对于测试比较实用同时必须和ReferenceQueue一起使用。

对于一组数据,我们可以通过HashMap的方式来添加一组SoftReference对象来临时保留一些数据,同时对于需要反复通过网络获取的不经常改变的内容,可以通过本地的文件系统或数据库来存储缓存。

1.3 Android(java)中常见的引起内存泄露的代码示例Android 主要应用在嵌入式设备当中,而嵌入式设备由于一些众所周知的条件限制,通常都不会有很高的配置,特别是内存是比较有限的。

如果我们编写的代码当中有太多的对内存使用不当的地方,难免会使得我们的设备运行缓慢,甚至是死机。

为了能够使得Android应用程序安全且快速的运行,Android 的每个应用程序都会使用一个专有的Dalvik 虚拟机实例来运行,它是由Zygote 服务进程孵化出来的,也就是说每个应用程序都是在属于自己的进程中运行的。

一方面,如果程序在运行过程中出现了内存泄漏的问题,仅仅会使得自己的进程被kill 掉,而不会影响其他进程(如果是system_process 等系统进程出问题的话,则会引起系统重启)。

另一方面Android 为不同类型的进程分配了不同的内存使用上限,如果应用进程使用的内存超过了这个上限,则会被系统视为内存泄漏,从而被kill 掉。

Android 为应用进程分配的内存上限如下所示:位置: /ANDROID_SOURCE/system/core/rootdir/init.rc 部分脚本# Define the oom_adj values for the classes of processes that can be# killed by the kernel. These are used in ActivityManagerService.setprop ro.FOREGROUND_APP_ADJ 0setprop ro.VISIBLE_APP_ADJ 1setprop ro.SECONDARY_SERVER_ADJ 2setprop ro.BACKUP_APP_ADJ 2setprop ro.HOME_APP_ADJ 4setprop ro.HIDDEN_APP_MIN_ADJ 7setprop ro.CONTENT_PROVIDER_ADJ 14setprop ro.EMPTY_APP_ADJ 15# Define the memory thresholds at which the above process classes will# be killed. These numbers are in pages (4k).setprop ro.FOREGROUND_APP_MEM 1536setprop ro.VISIBLE_APP_MEM 2048setprop ro.SECONDARY_SERVER_MEM 4096setprop ro.BACKUP_APP_MEM 4096setprop ro.HOME_APP_MEM 4096setprop ro.HIDDEN_APP_MEM 5120setprop ro.CONTENT_PROVIDER_MEM 5632setprop ro.EMPTY_APP_MEM 6144# Write value must be consistent with the above properties.# Note that the driver only supports 6 slots, so we have HOME_APP at the# same memory level as services.write /sys/module/lowmemorykiller/parameters/adj 0,1,2,7,14,15write /proc/sys/vm/overcommit_memory 1write /proc/sys/vm/min_free_order_shift 4write /sys/module/lowmemorykiller/parameters/minfree1536,2048,4096,5120,5632,6144# Set init its forked children's oom_adj.write /proc/1/oom_adj -16正因为我们的应用程序能够使用的内存有限,所以在编写代码的时候需要特别注意内存使用问题。

相关主题