OOM总结

本文主要信息是来自互联网,我只是本身作了一点总结和摘要。java

OOM发生的缘由android

简单的说经过不一样的内存分配方式对不一样的对象进行操做,会由于android系统版本的差别而产生不一样的行为。主要是2.0和4.0有较大的变化。web

在2.x系统中,dalvik allocated  + external allocated + 新分配的大小>= getMemoryClass() 就会发生OOM。编程

在4.x系统中,废除了external计数器,相似Bitmap的分配改到了Dalvik的java Heap 中申请,只要allocate + 新分配的内存>=getMemoryClass就会发生OOM。缓存

如何避免OOM网络

根据上面的介绍,避免OOM就是下降内存占用,和内存对象的重复利用,避免对象内存泄露,优化内存使用策略。多线程

1. 减少对象的内存占用app

1)尽量的使用android系统特有的对象,好比能够用arrayMap 和 SparseArray 代替hasMap,hasMap须要一个额外的对象来记录Mapping操做。SparseArray 更加高效,避免了对key和value的自动装箱和解箱。框架

2)避免使用Enum枚举,在android 官方文档里面就提到枚举一般须要更多的内存比 static constants。布局

3) 减小Bitmap对象的内存占用,通常状况下一般有2个措施:

  inSampleSize,缩放比例,在把图片载入内存以前,咱们就先计算一个合适的缩放比例

  decode format, 选择合适的解码格式ARGB_8888,每一个像素点占32位,ARGB_4444每一个像素点占16位,RGB_565每一个像素点占16位,ALPHA_8只有透明度,没有颜色。8位一个字节,因此在图片过大的时候,适当选择16位的解码格式,能够减小一半的图片内存占用。

4)可使用更小的图片,特别是在listview中,能够用较小的图片显示,只用在用户须要看大图的时候,才显示大图。

2. 内存对象的重复使用

1)android 系统自己内置了不少资源,好比字符串,颜色,图片,动画,样式等,这些资源能够直接使用,可是不足之处是不一样的android版本之间会有差别。

2) 注意在listview等对convertView的重复使用

3) Bitmap对象的复用,在listview等显示大量图片的控件里,须要使用LRU的机制来缓存处理好的bitmap。

利用inBitmap的高级特性提升android系统在bitmap分配与释放上的执行效率,在android 3.0和4.0上存在一些使用限制,inBitmap能够通知Bitmap解码去尝试使用已经存在的内存区域,这样就达到了图片内存重用的效果。InBitmap的使用限制以下:

1. 在SDK11-18之间,重用的Bitmap大小必须一致,在19之后,新申请的bitmap必须小于或者等于已经赋值过的Bitmap大小。

2. 新申请的bitmap必须和旧的bitmap具备相同的解码格式。不过能够经过创建bitmap对象池来解决这个问题。

4)避免在onDraw里面执行对象建立,由于onDraw会被频繁调用,这样就频繁执行对象建立,而迅速增长内存使用,频繁的GC,致使内存抖动。

5)使用StringBuilder代替String作字符的拼接

3 避免内存泄露

开源控件LeakCanary开源控件,能够很好的帮助咱们发现内存泄露状况。

 

1)注意Activity的泄露,这个是最严重的问题,通常有2种状况会致使内存泄露:

1.内部类引用致使Activity泄露:最典型的是Handler致使的,若是handler中有延迟的任务或者等待执行的任务队列过长,都有可能形成Activity泄露,解决方式: 在退出UI以前,执行remove Handler消息队列中的消息和runnable对象,或者使用static + weakReference的方式断开Handler与Activity之间存在的引用关系的目的。

2. Activity Context被传递到其余实体中,也可能致使自身被引用而发生泄露。

2)考虑使用Application Context而不是Activity Context

3)注意临时bitmap对象的及时回收,由于在建立一个临时的相对较大的bitmap对象,在进过变换后获得新的bitmap对象,那么应该尽快回收原始的bitmap,释放空间,尽可能不要使用createBitmap方法。

4)注意监听器的注销,特别是手动添加的监听器要及时remove。

5)注意缓存容易中的对象泄露,不要的缓存应该马上释放。

6)webview泄露,不一样版本,不一样厂商出货的ROM里面webview都存在很大差别,因此最好是webview开启另一个线程,桶AIDL与住线程通讯,根据业务须要适当的销毁进程。

7)Cursor对象及时关闭

4 内存使用策略优化:

1)谨慎使用large heap,在一些特殊状况下能够经过mainfest的application 标签添加largHeap=true来声明一个更大heap空间,可是因为总heap空间不变,会致使系统性能大打折扣。并且有的机器就不容许这样的操做。

2)综合考虑设备内存阀值与其余因素,设计合适的缓存大小。

3)onLowMemory 与 onTrimMemory

4) 资源文件须要选择合适的文件存放,不须要被拉伸的图片须要放到assets活nodpi目录下

5)try catch 某些大内存的分配操做,对于可能发生OOM的代码,能够考虑在catch里面尝试一次降级内存的操做。

6)谨慎使用static对象,由于static对象的生命周期过长。

7)特别留意单例对象中不合理的持有,由于单例的生命周期和应用保持一致,使用不合理容易致使对象泄露

8)尽可能使用IntentService,由于在它会处理完 任务后尽快结束本身。

9) 优化布局层次,减小内存消耗

10)谨慎使用抽象编程,抽象编程可以提代码的灵活些和可维护性,可是却会形成一个显著的额外内存消耗。

11)使用nano protobufs序列化数据,

12)谨慎使用依赖注入框架,虽然这个种方式简化代码,可是这些注入框架会经过扫描代码执行屡次初始化操做,这样会致使代码须要大量的内存空间来mapping代码,并且mapping pages会长时间保留在内存中。

13)谨慎使用多线程,使用多线程能够把应用中的部分组件运行在单独的进程中,扩大内存占用范围,可是必须谨慎使用,由于这个不经增长了代码逻辑复杂性,使用不当并且会显著增长内存,使用的前提是:须要运行一个常驻后台,并且这个任务不是轻量级的,能够考虑使用。

14)使用ProGuard提车不须要的代码,减小mapping代码须要的内存空间

15)谨慎使用第三方的libraries,特别是尽可能不要使用不是为了移动网络环境而编写的。

16)考虑使用不一样的方式优化内存占用。

 

本文不是原创,只是做为学习笔记记录

相关文章
相关标签/搜索