0%

Android-OOM分析

概述

Android App 的每个进程有一个最大内存限制,如果申请的内存资源(只有Java heap受这个限制, Native heap 不受限制)超过这个限制,系统就会抛出 OOM 错误。Java heap 占用过多整体来说可以分为两类:

  • 大内存对象,如 Bitmap 等。
  • 内存泄漏。

内存优化参考 Android性能优化之内存优化

OOM原因

OOM原因

OOM处理

堆内存不足

对于堆内存不足导致的OOM问题,发生Crash时的堆栈信息往往只是“压死骆驼的最后一根稻草”,并不能有效定位到问题。

堆内存分配失败,通常说明进程中大部分的内存已经被占用了,且不能被垃圾回收器回收,一般来说此时内存占用都存在一些问题,例如内存泄漏等。要想定位到问题所在,就需要知道进程中的内存都被哪些对象占用,以及这些对象的引用链路。而这些信息都可以在Java内存快照文件中得到,调用 Debug.dumpHprofData(String fileName) 函数就可以得到当前进程的Java内存快照文件(即HPROF文件)。

具体线上怎么处理的参考美团的 Probe(不开源) 和微信的 Matrix(开源)。主要是 hprof 文件的裁剪,Matrix 是基于 LeakCanary 上进行二次开发,所以监控原理基本是一致的。

线程数超出限制

通过 Thread.getAllStackTraces() 可以得到进程中的所有线程以及对应的堆栈信息。

一般来说,当进程中线程数异常增多时,都是某一类线程被大量的重复创建。所以我们只需要定位到这类线程的创建时机,就能知道问题所在。如果线程是有自定义名称的,那么直接就可以在代码中搜索到创建线程的位置,从而定位问题,如果线程创建时没有指定名称,那么就需要通过该线程的堆栈信息来辅助定位。

一般来说建议使用线程池。

FD数超出限制

在后台启动一个线程,每隔1s读取一次当前进程创建的FD数量,当检测到FD数量达到阈值时(FD最大限制的95%),读取当前进程的所有FD信息归并后上报。

/proc/pid/limits 描述着 Linux 系统对对应进程的限制,其中Max open files就代表可创建FD的最大数目。进程中创建的FD记录在 /proc/pid/fd 中,通过遍历它可以得到 FD 的信息。