Android内存优化四:OOM

Android内存优化一:java垃圾回收机制
Android内存优化二:内存泄漏
Android内存优化三:内存泄漏检测与监控
Android内存优化四:OOM
Android内存优化五:Bitmap优化

产生原因

android系统的每个进程或者每个虚拟机有个最大内存限制,如果申请的内存资源超过这个限制,系统就会抛出OOM错误。跟整个设备的剩余内存没太大关系。

03-21 21:05:28.771: E/dalvikvm-heap(13316): Out of memory on a 10485776-byte allocation.
03-21 21:05:28.779: E/AndroidRuntime(13316): java.lang.OutOfMemoryError

根据Java垃圾回收机制-内存分配策略:

  • 对象新生代Eden区中分配,当 Eden 空间不够时,虚拟机将发起一次Minor GC

  • 在Minor GC之前,会优先判断:当老年代最大可用的连续空间小于新生代所有对象总空间,且老年代最大可用的连续空间小于历次晋升到老年代对象的平均大小,则会触发Full GC

  • 当Full GC 之后,空间仍然不足,那么虚拟机会抛出 java.lang.OutOfMemoryError。

优化

  • 内存泄漏

内存泄漏的对象属于长期存活的对象,会进入老年代,并且由于无法被GC回收,一直占用着内存,导致内存不足而产生OOM,所以只需要解决内存泄漏就可以解决这一部分问题

  • 大对象

大对象是指需要连续内存空间的对象,比如Bitmap,很长的字符串以及数组。当内存剩余总空间不足,或者连续空间不足,也会产生OOM

解决大对象产生的OOM主要有以下几点

  • 合理分配所需内存,比如只需要展示100100的bitmap,但却申请了500500的内存,导致了内存浪费

  • 利用缓存,复用大对象的内存空间,避免在内存中申请多个大对象的内存

  • 数据结构

Java 提供的部分数据容器并不适合 Android,比如 HashMap,HashMap 需要中存储每一个键值对都需要一个额外的 Entry 对象。

Android 提供了几个优化后的数据容器,包括 SparseArray、SparseBooleanArray 以及 LongSparseArray。SparseArray 之所以更高效,是因为它的设计是只能使用整型作为 key,这样就避免了自动装箱的开销。

  • 业务调整

某些业务场景可能需要占用大量内存

  • 页面循环跳转A->B->A->B->A->B...,Activity栈太深,导致多个页面占用大量内存。

解决:比如设定一个阙值,最多只能同时存在3个A页面,超过则关闭最先打开的页面

  • fragment持有View

fragment与View具有不一致的生命周期,当fragment不可见时,如果仍持有View会导致无法View无法被回收,而View是内存大户,特别是ImageView。

不到万不得以,fragment不需要持有View,如果为了状态恢复等原因需要持有,可在onDestoryView中将View置空或者回收View持有的Bitmap等大对象

。。。。。

你可能感兴趣的:(Android内存优化四:OOM)