内存优化
高炳秋
2017年7月
一、前言(问题提出)
为了提高app的稳定性,一旦发生内存泄露,久而久之,就会出现oom,进而导致crash。
二、gc
分类
1、内存泄露:对象已经不再使用了,但是无法被内存回收;
2、内存溢出:对象太多,无法被无法,超过大小限制。
对象已死判断方法
1.如果有个对象引用他,则加1,当方法介绍时,则减去1。
2.可达性分析。
从gc root开始,如果不存在任何强引用链相连,说明可回收
引用分类
1.强引用:如果没有其他说明,都是强引用;
2.软引用(SoftReference):当内存不够时就回收
3.弱引用(WeakReference):gc触发时,就回收
4.虚引用(WeakReference):没用过
总结:一般都是强引用;如果担心对象发生内存泄露,就是使用弱引用,常见的有内部类等。
回收算法
1.标记-清除:判断对象是否已死,然后标记,逐个清除;
问题:产生了大量碎片,效率低
2.复制算法:把回收后还存活的对象复制到其他,然后清除剩下的;(分为eden:suivivor;8:1)复制到suivivor区;
3.标记-整理(老年代):先1,然后整理
4.分代:根据不同的年代采取不同的算法
总结:一般都是强引用;如果担心对象发生内存泄露,就是使用弱引用,常见的有内部类等。
分代策略
1.优先eden
2.大对象老年代
3.长时间的老年代
Minor gc:老年代小于新生代的最大值;
Full gc:老年代小于每次新生代升级平均值;
三、总结及备注
大对象处于老年代容易内存泄露;
一般不要主动调用System.gc();cpu消耗极大
四、实践
判断一个对象是否会内存泄露,主要看谁引用(调用)了该对象;如果其中的一个调用类声明周期大于该对象就可能发生内存泄露;
五、常见情况:
Handle:handle作为内部类,会持有外部类的引用,一直异步任务执行较久甚至卡住,就是导致外部Activity或者Fragment无法释放。可以修改为static,使用软引用;
mvp中的内存问题:vp互相引用,会导致p执行就时,v层无法释放。可以在onDestroy中解除引用(mView置空)或者使用eventbus解耦。
bitmap太大:会直接导致内存溢出,可以从图片质量(质量压缩),大小减少(inSampleSize)和Build.config三个方面减少bitmap大小。对于不在使用的图片可以调用recycle()方法回收内存。
单例:单例里面的成员变量都是无法释放的,请注意成员变量的大小。(类似Activity,Fragment)