文档章节

Android OOM 问题的总结

Line
 Line
发布于 2014/05/30 21:35
字数 1846
阅读 9943
收藏 23

问题: 安卓系统经常遇到OOM问题,如何优化和应对?

    Dalvik 主要管理的内存有 Java heap 和 native heap 两大块,而对于一个安卓应用来说,由于手机设备的限制,一般应用使用的RAM不能超过某个设定值,如果你想要分配超过大于该分配值的内存的话,就会报Out Of Memory 错误。不同产商默认值不太一样,一般常见的有16M,24M,32M,48M也就是说app的 Java heap + native heap < 默认值。只所以不等于是因为除了这2种我们主要关心的内存外,还有一些小块的内存块用做其他用途,如用于垃圾回收的markstack,markbits以及livebits。

导致OOM 有以下几种情况:

1 应用中需要加载大对象,例如Bitmap

一张在pc机上用的1024*768图片,如果直接用在手机屏幕这种小屏幕上,不仅没有提高显示质量,还容易使内存吃紧。假设照片是用ARGB_8888格式,那么一张1024&times;768的图片需要占用3M的内存, 4-5张就OOM了。bitmap分辨率越高,所占用的内存就越大,这个是以2为指数级增长的。

     

解决方案:当我们需要显示大的bitmap对象或者较多的bitmap的时候,就需要进行压缩来防止OOM问题。我们可以通过设置BitmapFactory.Optiions的inJustDecodeBounds属性为true,这样的话不会加载图片到内存中,但是会将图片的width和height属性读取出来,我们可以利用这个属性来对bitmap进行压缩。Options.inSampleSize 可以设置压缩比。


ps: 在android 2.3和以前的版本,bitmap对象的像素数据都是分配在native heap中的,所以我们在调试过程中这部分内存是在java heap中看不到的,不过在android 3.0之后,bitmap对象就直接分配在java heap上了,这样便于调试和管理。因此在3.0之后我们可以复用bitmap的内存,而不必回收它,不过新的bitmap对象要大小和原来的一样,到了android 4.4之后,就只要高宽不超过原来的就行了

   此外,java heap 的大小是动态变化的,它像是一个容器,只有水快满了,在允许的范围内,它会扩充它的容量。当水常处于较少的情况下它会缩小其容量. 上面说过android 2.3之前bitmap对象都是在native heap中分配的,如果我们在生成一个bitmap对象之前,在java heap 分配了一块较大的内存,即使之后这段内存被回收了,但是我们的java heap大小不可能一下子就随着这块内存的回收而缩小,它需要一个过程。而我们又要在native上分配一个bitmap对象的内存,如果这时候 默认值-java heap(未缩小) = native heap的值不足以分配给这个bitmap对象,那么就会报OOM错误。


2 持有无用的对象使其无法被gc,导致Memory Leak . 也就是我们说的内存泄漏。导致内存泄漏我了解的有以下几个方面。


2.1 静态变量导致的Memory leak

静态变量的生命周期和类是息息相关的,它们分配在方法区上,垃圾回收一般不会回收这一块的内存。所以我们在代码中用到静态对象,在不用的时候如果不赋null值,消除对象的引用的话,那么这些对象是很难被垃圾回收的,如果这些对象一多或者比较大的话,程序出现OOM的概率就比较大了。因为静态变量而出现内存泄漏是很常见的。

2.2 不合理使用Context 导致的Memory leak

  android 中很多地方都要用到context,连基本的Activty 和 Service都是从Context派生出来的,我们利用Context主要用来加载资源或者初始化组件,在Activity中有些地方需要用到Context的时候,我们经常会把context给传递过去了,将context传递出去就有可能延长了context的生命周期,最终导致了内存泄漏。例如 我们将activty context对象传递给一个后台线程去执行某些操作,如果在这个过程中因为屏幕旋转而导致activity重建,那么原先的activity对象不会被回收,因为它还被后台线程引用着,如果这个activity消耗了比较多的内存,那么新建activity或者后续操作可能因为旧的activity没有被回收而导致内存泄漏。所以,遇到需要用到context的时候,我们要合理选择不同的context,对于android应用来说还有一个单例的Application Context对象,该对象生命周期和应用的生命周期是绑定的。选择context应该考虑到它的生命周期,如果使用该context的组件的生命周期超过该context对象,那么我们就要考虑是否可以用application context。如果真的需要用到该context对象,可以考虑用弱引用来WeakReference来避免内存泄漏。

2.3 非静态内部类导致的Memory leak

非静态的内部类会持有外部类的一个引用,所以和前面context说到的一样,如果该内部类生命周期超过外部类的生命周期,就可能引起内存泄露了,如AsyncTask和Handler。因为在Activity中我们可能会用到匿名内部类,所以要小心管理其生命周期。 如果明确生命周期较外部类长的话,那么应该使用静态内部类。

2.4 Drawable对象的回调隐含的Memory leak

当我们为某一个view设置背景的时候,view会在drawable对象上注册一个回调,所以drawable对象就拥有了该view的引用了,进而对整个context都有了间接的引用了,如果该drawable对象没有管理好,例如设置为静态,那么就会导致Memory leak


在手机版QQ中,对于图片的处理方法是先加载用户发送的图片的小图,只有用户点击了才去加载大图,这样即节省了流量也能防止bitmap过大造成OOM 。另外,对于离开屏幕内容的图片,也要及时的回收,不然聊天记录一多也就OOM了。 对于回收的图片,我们可以采用软引用来做缓存, 这样在内存不吃紧的情况下就能提高交互性,因为在Java中软引用在内存吃紧的时候才会被垃圾回收,比较适合用做cache.另外在Android 3.1版本起,官方还提供了LruCache来进行cache处理。对于不用的Bitmap对象,我们要及时回收,否则会造成Memory leak ,所以当我们确定Bitmap对象不用的时候要及时调用Bitmap.recycle()方法来使它尽早被GC


               


© 著作权归作者所有

共有 人打赏支持
Line
粉丝 4
博文 13
码字总数 9580
作品 0
汕头
程序员
私信 提问
Android进程系列第六篇---LowmemoryKiller机制分析(上)

一、内容预览 二、概述 前面进程系列已经更新了五篇,本文(基于Android O源码),梳理LMK杀进程机制上篇,主要总结AMS和LowmemoryKiller通信的方式以及LowmemoryKiller的原理。 Android进程...

LooperJing
2018/10/12
0
0
Android Bitmap变迁与原理解析(4.x-8.x)

App开发不可避免的要和图片打交道,由于其占用内存非常大,管理不当很容易导致内存不足,最后OOM,图片的背后其实是Bitmap,它是Android中最能吃内存的对象之一,也是很多OOM的元凶,不过,在...

看书的小蜗牛
2018/05/22
0
0
移动开发者必须知道的Android框架推荐

一些总结出来的Android快速开发框架,全部都是开源框架,附带项目地址,是开发学习的绝佳资料。 thinkAndroid项目 github地址:https://github.com/white-cat/ThinkAndroid 功 能:ThinkAndr...

程序袁_绪龙
2014/09/02
0
0
Android进程系列第八篇---LowmemoryKiller机制分析(下)

前面进程系列已经更新了七篇,本文(基于kernel 3.18),基于前两篇博客,继续梳理LMK杀进程机制下篇,主要总结LowmemoryKiller的中kernel的原理部分。 Android进程系列第一篇---进程基础 An...

LooperJing
2018/10/16
0
0
关于 Android 进程保活,你所需要知道的一切

早前,我在知乎上回答了这样一个问题:怎么让 Android 程序一直后台运行,像 QQ 一样不被杀死?。关于 Android 平台的进程保活这一块,想必是所有 Android 开发者瞩目的内容之一。你到网上搜...

oschina
2016/04/21
10.4K
36

没有更多内容

加载失败,请刷新页面

加载更多

zabbix安装配置

环境 系统:centos7.5软件版本: mysql: 5.7 zabbix: 3.4.15内网: Port: 10051 IP: 192.168.2.71外网: Port: 34521 Domain: freefrp.cnAgent被动模式(默认) ...

亦漩
17分钟前
1
0
一看就能学会的H5视频推流方案

本文由云+社区发表 作者:周超 导语 随着直播平台爆发式增长,直播平台从 PC 端转战移动端,紧跟着直播的潮流,自己学习实现了一套简单的 H5 视频推流的解决方案,下面就给小伙伴们分享一下自...

腾讯云加社区
19分钟前
3
0
Spring Boot 2.X优雅停止

本文章介绍了正常关闭Spring Boot 应用程序的过程。许多开发人员和架构师总是讨论SpringBoot的应用设计、流量负载、框架和应用模式,但很少有人讨论关闭阶段。生命周期意识可以说一个真正资深...

WUBAOQUAN
30分钟前
3
0
Linux Redis 高可用之主从复制

Redis主从复制简介 和MySQL主从复制的原因一样,Redis虽然读取写入的速度都特别快,但是也会产生读压力特别大的情况。为了分担读压力,Redis支持主从复制,Redis的主从结构可以采用一主多从或...

我最喜欢三大框架
36分钟前
2
0
HTML5技术分享之自动化构建工具gulp使用

gulp是是前端开发对代码进行构建的工具,是基于 Nodejs 的自动任务运行器,他能自动化地完成 javascript/coffee/sass/less/html/image/css 等文件的的测试、检查、合并、压缩、格式化、浏览器...

纤纤郡主
42分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部