资源描述
Memory AnalysisJava 层Native 层Java 层强引用即使虚拟内存吃紧,也不会导致对象被回收。弱引用当虚拟机OOM前,软引用会被强制回收。软引用虚引用Android 每个应用程序都会使用一个专门的Dalvik虚拟机实例来运行,它是由Zygote服务进程孵化出来的。一旦程序出现内存泄漏的问题,仅仅会使自己的进程被kill掉,不会影响其他进程。不同类型的进程有不同的内存使用上限。init.rc引起内存泄漏的情况查询数据库没有关闭游标Cursor cursor=null;try cursor=getContentResolver().query(uri.);if(cursor!=null&cursor.moveToNext().finally if(cursor!=null)try cursor.close();构造Adapter时,没有使用缓存的convertView。public View getView(int position,View convertView,ViewGroup parent)View view=null;if(convertView!=null)view=convertView;populate(view,getItem(position);.else view=new Xxx(.);.return view;初始化时ListView会从BaseAdapter中根据当前屏幕布局实例化一些数量的View,同时ListView会将这些view对象缓存起来。当向上滚动Listview时,原先位于最上面的listview会被用来构造新出现的最下面的listItem。这个构造过程是由getView对象方法完成的。缓存的数据放在convertView中。因此,如果在getView中每次都不去使用convertView重新实例化一个View对象,即会导致内存泄漏。应用导致的内存泄漏应用导致的内存泄漏一个生命周期短的对象A,被一个生命周期长的对象B引用。例子:假设我们希望在锁屏界面(LockScreen)中,监听系统中的电话服务以获取一些信息(如信号强度等),则可以在LockScreen 中定义一个PhoneStateListener 的对象,同时将它注册到TelephonyManager 服务中。对于LockScreen 对象,当需要显示锁屏界面的时候就会创建一个LockScreen 对象,而当锁屏界面消失的时候LockScreen 对象就会被释放掉。但是如果在释放LockScreen 对象的时候忘记取消我们之前注册的PhoneStateListener 对象,则会导致LockScreen 无法被垃圾回收。如果不断的使锁屏界面显示和消失,则最终会由于大量的LockScreen 对象没有办法被回收而引起OutOfMemory,使得system_process 进程挂掉。分析步骤以查询光标没有关闭导致内存泄漏为例利用Heap,找到内存泄漏的操作。(先要作GC)分析步骤使用Allocation Tracker对这一操作进行跟踪;重点查看相同行中多次申请的操作,结合代码分析。Allocation Tracker工具只反映出了Allocation的操作记录。有可能显示出来的对象其实已经释放或者会被GC。如果分析不出来,需要通过MAT工具进行进一步的查找。MAT(Memory Analyzer Tool)下载HPROF文件。使用Eclipse Memory Analyzer工具打开。如果无法打开需要使用Android自带的hprof-conv.exe 工具进行转换。抓取两份hprof文件,操作一两次,case gc抓取第一份,重复多次有内存泄漏的操作,case gc 抓取第二份。使用Histogram比较这两份文件的差异。找到操作前后通过GC后增加的对象,断定这些对象有内存泄漏的可能。Shallow size就是对象本身占用内存的大小,不包含对其他对象的引用,也就是对象头加成员变量(不是成员变量的值)的总和。在32位系统上,对象头占用8字节,int占用4字节,不管成员变量(对象或数组)是否引用了其他对象(实例)或者赋值为null它始终占用4字节。Retained size是该对象自己的shallow size,加上从该对象能直接或间接访问到对象的shallow size之和。换句话说,retained size是该对象被GC之后所能回收到内存的总和。由于通过MAT找到了内存泄漏的对象,但却无法确认对象申请的过程。因此,这时可以再使用Allocation Tracker查找该对象对应的申请过程。内存泄漏情况再分析常见的内存泄漏情况JNI层内存泄漏
展开阅读全文