碎碎念
Android系统是基于Linux内核开发的操作系统。但是也有差异的。而内存管理就是其中的一处。
- 传统的
Linux系统的使用的是Swap交换空间。大致就是当系统内存空间不够的时候,就会释放一些长时间没有使用的程序的内存空间。这些被释放的空间临时存储在swap空间中。而这部分空出来的内存,就提供给当前需要使用的程序使用。等程序再次要运行的时候被保存在swap空间中的数据会再次被恢复。 - 而在
Android又是另一种策略,Android会持续保存你所运行的进程(为了下次的相应更加的迅速)这样就会存在有一个问题,那就是内存会随着进程的数量随之增大。当系统内存不足的时候,就会触发OOM killer来对进程管理。OOM killer就是根据一系列策略和规则来决定杀死进程。
那么,它的规则和策略是什么呢?
Android 进程的分类
在了解它的规则之前,我们先来看下Android对进程的分类。
- 前台进程( foreground process):顾名思义就是当前正在运行的进程。其中可以是
活动执行onResume方法,或者广播正在执行onReceive中这类进程都可以被定义成前台进程。当然前台进程也有可能被销毁。当系统的内存空间不足以支撑当前存在的前台进程,这些进程还是会被杀死。 - 可见进程(visible process):正在执行用户可知的工作。这样的话终止它就会影响到用户的体验。其中可以是
活动的onPause被调用了,但是对用户还是可见的(比方说当前的活动是个透明的对话框,可以看到之前的活动)这样可以被定义为可见进程。可见进程被杀死的优先级会高于前台进程 - 服务进程(service process):是使用
startService()方法启动的服务。虽然这些进程对用户来说不是直接可见的,但它们通常在做用户关心的事情(比如上传或下载后台网络数据),所以系统将始终保持这些进程的运行,除非没有足够的内存来保留所有前台进程和可见进程服务的优先级也会随着运行时间的正常而变大。(运行比较久的服务,会变成缓存进程) - 缓存进程(cached process) :缓存的进程是当前不需要的进程,所以当其他地方需要内存时,系统可以随意终止它。当系统内存不足的时候会优先确保所有的缓存线程都被杀死,还不足以提供内存的时候,才会考虑杀死服务进程。
当我们了解了进程的这些分类,就会知道,当应用程序属于缓存进程的时候最容易被OOM killer杀死,如果不想让OOM killer杀死的话,应该尽量的让我们的应用程序属于前台进程。
当然这只是官方文档上的说明,我们能不能真正量化它的优先级呢?
OOM_ADJ 介绍
OOM_ADJ(Out of Memory Adjustment)是android系统在内存不足情况下进行内存调整的重要参数。我们可以根据这个值,来查看进程被杀死的有限级。OOM_ADJ的值越大,被OOM killer杀死的优先级越高。
我们可以通过adb shell ps来查看进程的PID,然后通过PID获取到OOM_ADJ的值

可以看到当前的微信的oom_adj的值为8,那么我将微信切换到前台看看会不会发生变化.

OOM killer杀死了,同时也再次证明了,缓存进程被OOM killer杀死的优先级要高。
进程保活的一些看法
进程保活的本质,就是让APP尽量不被系统杀死。就算杀死了,也要重新force出来。看过很多文章介绍这个,其中包含有
- 通过监听各种广播,然后来唤醒
APP - 全家桶系列,比如说你装了
某宝就会有惊喜。 1px让进程属于可见进程- 疯狂启动服务
- 白名单
上述的很多方式,随着google的不断升级,已经失效了。
- Android M Doze Mode
- Android N Limit Implicit Broadcast
- Android O Background Service Limitations
真的很讨厌,那种杀不死的小强。