一个给开发者使用的Android App内存清理、监控工具,能够获取当前手机的内存使用比率,可用内存大小,检查一个APP是否存在内存泄漏。html
而且整理了一些优化内存的方式。android
相似360卫士的 加速球,获取系统已用内存比率、可用内存大小,一键清理。git
能够用于测试本身开发的Activity、Fragment健壮性,模拟Activity、Fragment被回收的场景,测试本身的程序是否无缺的保存、恢复当前场景。github
好比:打开你开发的某个Activity、Fragment,切到后台,清理一次内存,在将其切回前台后,看会不会出现空指针异常,以及程序状态是否被恢复。数据库
Android系统中的内存和Linux系统同样,存在着大量的共享内存。每一个APP占内存会有私有和公共的两部分,咱们能够经过App的Pss值,能够获取到这两部份内存。数据结构
Pss(Proportional Set Size):实际使用的物理内存,即:自身应用占有的内存+共享内存中比例分配给这个应用的内存。工具
经过改程序,每隔1秒,获取一次被监控App的Total Pss值。测试
使用某个功能(可能会致使OOM的那些都要试试),查看Pss是否飙升,或者使用过许久都没有下降。优化
若是使用后飙升而且长时间都降不下来,那就说明确定会致使OOM(对象使用过以后还被引用着未释放),若是使用以后Total Pss飙升,可是使用过以后能降下来,也可能会致使OOM,咱们仍是须要去一点一点排查是什么缘由致使的。ui
若是使用后飙升而且长时间都降不下来,咱们就须要使用MAT来进一步分析问题所在。
Android的虚拟机是基于寄存器的Dalvik,它的最大堆大小通常比较小(最低端的设备16M,后来出的设备变成了24M,48M等等),所以咱们所能利用的内存空间是有限的。若是咱们使用内存占用超过了必定的限额后就会出现OutOfMemory的错误。
可能会致使内存溢出的状况有如下几种:
若是一个变量为static变量,它就属于整个类,而不是类的具体实例,因此static变量的生命周期是特别的长,若是static变量引用了一些资源耗费过多的实例,例如Context,就有内存溢出的危险。
Google开发者博客,给出了一个例子:http://android-developers.blogspot.jp/2009/01/avoiding-memory-leaks.html 专门介绍长时间的引用Context致使内存溢出的状况。
这种状况:
静态的sBackground变量,虽然没有显式的持有Context的引用,可是: 当咱们执行view.setBackgroundDrawable(Drawable drawable);以后。 Drawable会将View设置为一个回调(经过setCallback()方法),因此就会存在这么一个隐式的引用链:Drawable持有View,View持有Context sBackground是静态的,生命周期特别的长,就会致使了Context的溢出。
解决办法: 1.不用activity的context 而是用Application的Context; 2.在onDestroy()方法中,解除Activity与Drawable的绑定关系,从而去除Drawable对Activity的引用,使Context可以被回收;
长周期内部类、匿名内部类,如Handler,Thread,AsyncTask等。
HandlerOutOfMemoryActivity所示的是Handler引起的内存溢出。
ThreadOutOfMemoryActivity所示的是Thread引起的内存溢出。
AsyncTaskOutOfMemoryActivity所示的时AsyncTask引起的内存溢出。
通常是由于尝试加载过大的图片到内存,或者是内存中已经存在的过多的图片,从而致使内存溢出。
正常状况下,若是查询获得的数据量较小时不会有内存问题,并且虚拟机可以保证Cusor最终会被释放掉,若是Cursor的数据量特表大,特别是若是里面有Blob信息时,应该保证Cursor占用的内存被及时的释放掉,而不是等待GC来处理。
若是在某个Activity中使用 Singleton instance = Singleton.getInstance(this);
就会形成该Activity一直被 Singleton
引用着,不能释放。这时候,正确的作法是使用 getApplicationContext()
来替代 Activity的Context
,这样就能避免内存泄露。
- 尽可能使用9path
- Adapter要使用convertView
- 各类监听,广播等,注册的同时要记得取消注册
- 使用完对象要及时销毁,能使用局部变量的不要使用全局变量,功能用完成后要去掉对他的引用
- 切勿在循环调用的地方去产生对象,好比在getview()里new OnClicklistener(),这样的话,拖动的时候会new大量的对象出来。
- 使用Android推荐的数据结构,好比HashMap替换为SparseArray,避免使用枚举类型(在Android平台,枚举类型的内存消耗是Static常量的的2倍)
- 使用lint工具优化工程
- 字符串拼接使用StringBuilder或者StringBuffer
- 尽可能使用静态匿名内部类,若是须要对外部类的引用,使用弱引用
- for循环的使用 用 final int size = array.length; for(int i = 0; i< size;i++) 来替代: for(int i =0;i < array.length;i++)
最后。
我整理了一些开发中可能会致使内存溢出的状况,放在com.cundong.memory.wrong中,而且给出了优化方法,放在com.cundong.memory.right中。