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

OOM发生的原因

简单的说通过不同的内存分配方式对不同的对象进行操作,会因为android系统版本的差异而产生不同的行为。主要是2.0和4.0有较大的变化。

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

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

如何避免OOM

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

1. 减小对象的内存占用

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)考虑使用不同的方式优化内存占用。

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

OOM总结的更多相关文章

  1. 【知识必备】内存泄漏全解析,从此拒绝ANR,让OOM远离你的身边,跟内存泄漏say byebye

    一.写在前面 对于C++来说,内存泄漏就是new出来的对象没有delete,俗称野指针:而对于java来说,就是new出来的Object放在Heap上无法被GC回收:而这里就把我之前的一篇内存泄漏的总 ...

  2. ValueInjecter----最好用的OOM(以微信消息转对象举例)

    使用数据实体的好处我这里就不多说了,但大家享受这些好处的时候,难免也对那些琐碎的赋值代码感到厌烦,基于此,我认为掌握一个oom的使用,还是很有必要的. 这种类型的工具有很多,比如automapper, ...

  3. 五步掌握OOM框架AutoMapper基本使用

    本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明原文地址 www.cnblogs.com/tdws  写在前面 OOM顾名思义,Object-Object-Mapping实体间相互转换,Aut ...

  4. Android设置图片内存溢出(OOM)问题——Android开发进阶之路6

    ImageView设置图片必备常识技术: Android设备会给每个应用分配16M的内存空间,如果你设置的图片的比较大且同一个页面有多个时,经常会报OOM错误导致程序奔溃.所以在这种情况下我们必须要对 ...

  5. MySQL 5.6 OOM 问题解决分享【转】

    本文来自:杨德华的原创分享 | MySQL 5.6 OOM 问题解决分享 延伸阅读:Linux的内存回收和交换 当遇到应用程序OOM的时候,大多数时候只能用头疼来形容,应用程序还可以通过引流来临时重启 ...

  6. Android 内存管理 &Memory Leak & OOM 分析

    转载博客:http://blog.csdn.net/vshuang/article/details/39647167 1.Android 进程管理&内存 Android主要应用在嵌入式设备当中 ...

  7. OOM killer

    Linux下有一种OOM KILLER 的机制,它会在系统内存耗尽的情况下,启用自己算法有选择性的kill 掉一些进程. 1. 为什么会有OOM killer 当我们使用应用时,需要申请内存,即进行m ...

  8. Spark java.lang.outofmemoryerror gc overhead limit exceeded 与 spark OOM:java heap space 解决方法

    引用自:http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece7631046893b4c4380146d96864968d4e414c42246 ...

  9. Redis: OOM command not allowed when used memory > ‘maxmemory’

    现象 日志里出现异常: OOM command not allowed when used memory > 'maxmemory' 原因 内存已满,不允许再存数据了,可以通过redis-cli ...

  10. 总结Android中遇见的OOM

    一 .Android应用中内存泄漏几种的原因: 1.单例模式导致的内存泄漏: 当调用getInstance时,如果传入的context是Activity的context.只要这个单例没有被释放,这个A ...

随机推荐

  1. asp.net "callback" 和 "postback" 的区别.

    下图解释了基于 asp.net的 "postback" 和 "callback"的生命周期: Postback 是在将 整个页面的数据 从 client 提交到 ...

  2. MVC校验特性

    1.前端引入3个脚本       ①jq脚本   ②jQuery.Validate.js  ③jquery.validate.unobtrusive.js(异步验证) 2.后端加特性 在表对应的Mod ...

  3. jquery的鼠标移入移出事件hover、mouseenter、mouseleave、mouseover、mouseout

    hover:鼠标进入元素的子元素时不会触发‘鼠标移开’的事件: mouseenter.mouseleave:效果与hover相同: mouseover: 鼠标进入元素和进入它的子元素时都会触发‘mou ...

  4. 3月19日 html(一) html基础内容

    ---恢复内容开始--- 今天学习了html的第一节课,是些比较简单的基础知识,知道如何向网页里添加文本.图片.表格.超链接之类的,如何去编写这些代码. html(hyper text makeup ...

  5. Ubuntu 配置swftools(Ubuntu14.04)

    1.下载文件 wget http://swftools.org/swftools-0.9.0.tar.gz .tar.gz wget http://www.ijg.org/files/jpegsrc. ...

  6. iOS开发 - 不进入待机(屏幕保持唤醒)---UIApplication学习

    iOS开发 - 不进入待机(屏幕保持唤醒)---UIApplication学习 如果你不希望应用运行时 iPhone 进入锁屏待机状态,加入下面这行代码即可 [[UIApplication share ...

  7. Qt跨线程信号和槽的连接(默认方式是直连和队列的折中)

    Qt支持三种类型的信号-槽连接:1,直接连接,当signal发射时,slot立即调用.此slot在发射signal的那个线程中被执行(不一定是接收对象生存的那个线程)2,队列连接,当控制权回到对象属于 ...

  8. WCF的基本知识-仅Http绑定的认知

    有关WCF,这3个字母代表的含义,鄙人不会在此细说.喜欢或者不喜欢的,大家勿喷. 入正题,微软从设计.net框架开始,就一直着力于解决程序间的互通信问题.从古老的套接字(Socket)通信到后来的Re ...

  9. (7)如何得到所有的 "水仙花数" ?

    本程序转载自:如何得到所有的水仙花数 感谢Android_iPhone(日知己所无),preferme(冰思雨)等人: package test; import java.math.BigIntege ...

  10. 关于as3实现对任何对象进行深刻复制的思考

    无意中看到关于as3深度复制思考的文章,觉得不错,于是转来记录以后用到可以参考. 转载来源:http://xmchcly.iteye.com/blog/1307425,下面是转文: 通过 ByteAr ...