持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第17天,点击查看活动详情
Android低内存杀进程机制
android基于进程中运行的组件及其状态规定链默认的五个回收优先级:
- Empty process(空进程)
- Background process(后台进程)
- Service process(服务进程)
- Visible process(可见进程)
- Foreground process(前台进程)
系统需要进行内存回收时最先回收空进程,然后是后台进程,以此类推最后才会回收前台进程(一般情况下前台进程就是与用户交互的进程了,如果连前台进程都需要回收那么此时系统几乎不可用了)。
ActivityManagerService 会对所有进程进行评分(存放在变量adj中),然后再讲这个评分更新到内核,由内核去完成真正的内存回收( lowmemorykiller , Oom_killer )。这里只是大概的流程,中间过程还是很复杂
什么是OOM
OOM(OutOfMemoryError)内存溢出错误,在常见的Crash疑难排行榜上,OOM绝对可以名列前茅并且经久不衰。因为它发生时的Crash堆栈信息往往不是导致问题的根本原因,而只是压死骆驼的最后一根稻草。
发生OOM的条件
- Android 2.x系统 GC LOG中的dalvik allocated + external allocated + 新分配的大小 >=getMemoryClass()值的时候就会发生OOM。 例如,假设有这么一段Dalvik输出的GC LOG: GC_FOR_MALLOC free 2K, 13% free 32586K/37455K, external 8989K/10356K, paused 20ms, 那么32586+8989+(新分配23975)=65550>64M时,就会发生OOM。
- Android 4.x系统 Android 4.x的系统废除了external的计数器,类似bitmap的分配改到dalvik的java heap中申请,只要allocated + 新分配的内存 >= getMemoryClass()的时候就会发生OOM
OOM原因分类
- java堆内存溢出
- 无足够连续内存空间
- FD数量超出限制
- 线程数里超出限制
- 虚拟内存不足
常见内存分析的命令
- dumpsys meminfo 适用场景: 查看进程的oom adj,或者dalvik/native等区域内存情况,或者某
个进程或apk的内存情况,功能非常强大;
-
procrank 适用场景: 查看进程的VSS/RSS/PSS/USS各个内存指标;
-
cat /proc/meminfo 适用场景: 查看系统的详尽内存信息,包含内核情况;
-
free 适用场景: 只查看系统的可用内存;
-
showmap 适用场景: 查看进程的虚拟地址空间的内存分配情况;
-
vmstat 适用场景: 周期性地打印出进程运行队列、系统切换、CPU时间占比等情况;
内存分析工具
- MAT
- profiler
- LeakCanary