Android 程序由java语言编写,android的内存管理与java相似,通过new为对象分配内存,所有对象在java堆内分配空间,对象回收有个垃圾回收器来完成。GC就是垃圾收集的意思(Gabage Collection)。
每个Android app底层都对应一个Dalvik虚拟机,它的最大堆大小一般是16M,有的机器为24M。
也就是说我们所能利用的内存空间是有限的。如果我们的内存占用超过了一定的水平就会出现OutOfMemory的错误。
内存问题主要有两个方面:
1.程序设计中保存了多个大内存的对象(缓存设计),导致超过可用内存限制;
2.程序的错误,长期持有已经不被引用的内存对象,导致占用无谓的内存空间,造成内存泄露。
Android触发内存泄露的条件:
Android 系统中内存回收的触发点大致可分为三种情况:
1.用户程序调用 StartActivity(), 使当前活动的 Activity 被覆盖;
2.用户按 back 键,退出当前应用程序;
3.启动一个新的应用程序。这些能够触发内存回收的事件最终调用的函数接口就是 activityIdleInternal()。
Android内存检测方法:
DDMS工具:
前提:安装debug包
内存监测工具 DDMS --> Heap
1. 手机连接电脑,打开“USB调试”模式 。
2. 链接成功后,在DDMS的Devices视图中将会显示手机设备的序列号,以及设备中正在运行的部分进程信息;
3. 点击选中想要监测的进程,比如com.taobao.taobao进程;
4. 点击选中Devices视图界面中最上方一排图标中的“Update Heap”图标;
5. 点击Heap视图中的“Cause GC”按钮;
6. 此时在Heap视图中就会看到当前选中的进程的内存使用量的详细情况。
说明:
a) 点击“Cause GC”按钮相当于向虚拟机请求了一次gc操作;
b) 当内存使用信息第一次显示以后,无须再不断的点击“Cause GC”,Heap视图界面会定时刷新,在对应用的不断的操作过程中就可以看到内存使用的变化;
如何才能知道我们的程序是否有内存泄漏的可能性呢。这里需要注意一个值:Heap视图中部有一个Type叫做data object,即数据对象,也就是我们的程序中大量存在的类类型的对象。在data object一行中有一列是“Total Size”,其值就是当前进程中所有Java数据对象的内存总量,一般情况下,这个值的大小决定了是否会有内存泄漏。可以这样判断:
a) 不断的操作当前应用,同时注意观察data object的Total Size值;
b) 正常情况下Total Size值都会稳定在一个有限的范围内,也就是说由于程序中的的代码良好,没有造成对象不被垃圾回收的情况,所以说虽然我们不断的操作会不断的生成很多对 象,而在虚拟机不断的进行GC的过程中,这些对象都被回收了,内存占用量会会落到一个稳定的水平;
c) 反之如果代码中存在没有释放对象引用的情况,则data object的Total Size值在每次GC后不会有明显的回落,随着操作次数的增多Total Size的值会越来越大,
直到到达一个上限后导致进程被kill掉。
总之,使用DDMS的Heap视图工具可以很方便的确认我们的程序是否存在内存泄漏的可能性。
使用的步骤:
1.程序出现内存泄露,进入终端导出hprof数据,输入:adb pull /sdcard/MemoryMonitor/com.taobao.taobao/leak_activity/2013-12-30-09-49-32/com.taobao.taobao.hprof。在当前路径下保存com.taobao.taobao.hprof
2.使用MAT分析hprof文件,这里需要安装eclipse插件MAT。
3.原始生成的hprof,需要转换格式,才能被MAT解析,使用adt的sdk下tools里的hprof-conv命令转换:
hprof-conv 保存hprof的原始路径 转换后的hprof的存放路径和存放名
如:
hprof-conv /Users/com.taobao.taobao.hprof /Users/orderlist.hprof