什么是OOM?
当前占用的内存加上我们申请的内存资源超过了Dalvik虚拟机的最大内存限制就会抛出Out Of Memory异常。
一些容易混淆的概念:
- 内存溢出:指的就是OOM。
- 内存抖动:是短时间内大量的对象被创建,然后又被马上释放这些顺间所产生对象,会严重点用内存区【最近刚分配的对象会放在Young Generation区域】,由于刚创建的对象又快速被释放这样就会对堆内存的压力从而触发更多的GC。
- 内存泄漏:这个是开发中比较常见的,指的是进程中的某些对象已经没有其它对象引用它了,但是它又能直接或间接的引用GC ROOT,也就是还能引用到没有被回收的对象,导至GC无法产生作用,当内存泄漏累积到一定程度就会引发OOM。
如何解决OOM:
- 有关bitmap:
①、图片的显示:在ListView中加载大图时去做滑动监听,只有是停止状态才去网络加载图片。
②、及时释放内存:因为一个图片存在两部分内存:一是java层的内存,二是C层的内存,而C层的内存是不会被JVM所回收的,所以需要及时去调用recycle()方法对底层的内存进行释放,另外需要注意:并非不掉用recycle()方法就容易造成内存溢出,因为当app被杀掉之后C层的也会主动被释放的。
③、图片的压缩:insamplesize。
④、inBitmap属性:3.0系统以后才支持它,主要就是指的复用内存块,不需要在重新给这个bitmap申请一块新的内存,避免了一次内存的分配和回收,从而改善了运行效率。inBitmap类似对象池的技术原理,避免内存的频繁的创建和销毁带来性能的损耗。使用inBitmap能高提升bitmap的循环效率。在Google发布的第二季性能优化都有提到inBitmap技术 使用inBitmap前,每创建一个bitmap需要独占一块内存:使用inBitmap后,多个bitmap会复用同一块内存
所以使用inBitmap能够大大提高内存的利用效率,但是它也有几个限制条件:
1.在SDK 11 -> 18之间,重用的bitmap大小必须是一致的,例如给inBitmap赋值的图片大小为100-100,那么新申请的bitmap必须也为100-100才能够被重用。从SDK 19开始,新申请的bitmap大小必须小于或者等于已经赋值过的bitmap大小。
2.新申请的bitmap与旧的bitmap必须有相同的解码格式,例如大家都是8888的,如果前面的bitmap是8888,那么就不能支持4444与565格式的bitmap了,不过可以通过创建一个包含多种典型可重用bitmap的对象池,这样后续的bitmap创建都能够找到合适的“模板”去进行重用。
博客参考:http://blog.csdn.net/zjd934784273/article/details/54670064⑤、捕获异常。避免实例化Bitmap时因内存不足抛异常。
- 其它方法:
①、listView优化:convertView / LRU。
②、避免在onDraw()方法里面执行对象的创建。因为跟之前内存抖动的情况类似,因为可能存在大量临时对象又迅速被回收,而内存抖动多了最终也会引起OOM。
③、谨慎使用多进程:这是官方给出的优化,如果APP的业务木有达到一定的程序尽量少用多进程,因为多进程的代码处理会更加复杂,很容易造成莫名的crash。