谈谈Android低内存进程回收
有人在知乎上问了一个问题:Android onTrimMemory方法的一些疑惑。理解这个问题需要知道android内存不足时,回收进程的流程。
android进程回收主要涉及两个组件:ActivityManagerService(Ams)和lowmemorykiller。
当手机内存不足时,lowmemorykiller就要开始杀进程了。但是lowmemorykiller呢只知道进程占用的内存大小,不知道进程对用户的重要性。Ams则负责管理android四大组件,当然知道进程的重要性了,所以呢还需要与Ams充分交换意见。
盗张图(侵删)
当app状态发生改变时,比如退到后台时,ams会对app的进程计算出一个值,即Oomadj(ams#computeOomAdjLocked),然后把这个值传给linux内核,lowmemorykiller呢就可以拿到这个值了,lowmemorykiller则就有了所有app进程的Oomadj值,即进程对用户的重要程度。当手机内存不足时,lowmemorykiller就有了足够的信息决定干掉哪个进程了。
那,lowmemorykiller决定干掉哪个进程呢?
这个要根据手机还有多少空闲内存,比如还有16MB空闲内存,如下lowmemorykiller.c
1 | static short lowmem_adj[6] = { |
16MB在lowmem_minfree第三个位置,取lowmem_adj第三个位置即6,ok所有Oomadj大于6的进程就被选中了。而lowmemorykiller不是把这些选中的进程都干掉,而是先干掉oomAdj最大而且占用内存最大的进程。如下lowmemorykiller.c#lowmem_scan:
1 | for_each_process(tsk) { |
总之一句话:进程对用户越不重要(Oomadj值就越大),占用内存越大,进程就越容易被干掉。
应对策略:
ams计算出一个危险的Oomadj值会调用onTrimMemory通知app,此时app应该把不重要的内存释放掉,只要比友商app占用的内存小被lowmemorykiller干掉的概率就小。
当然我们也可以先把忧伤的app干掉…帮用户释放内存(开玩笑啦)
如果我们的app能预置到手机中,并且manifest设置为persistence(Oomadj=0),或者coreserver则不必担心被lowmemorykiller干掉了。不过还有可能被linux层的oomkiller干掉的。当然这也是某些手机预置一堆app导致越用越慢的一个原因,所以我们尽量把这些预置app卸载掉