三、内存管理
当应用程序关闭后,后台对应的进程并没有真正退出,以便下次再启动时能够快速启动。
当系统内存不够时,AMS会根据一定的优先规则退出优先级较低的进程。
1.应用关闭而进程不退出
应用程序窗口关闭即Activity执行finish()对应的进程没有退出而会一直保存。
每个应用程序对应一个ActivityThread类,ActivityThread初始化之后会进入Looper.loop()无限循环。以后依靠消息机制执行,即当有消息时处理消息,没有消息时该线程会进入到sleep状态。
在Linux内核调度中,如果一个线程的状态为sleep,本身不会占用CPU时间片,因此不会影响当前进程的执行速度。
以下三种情况会重新唤醒线程重新执行:
定时器中断。应用程序设置定时器任务,当定时器发生时,系统会回调定时器,在定时器任务中向looper主线程发送消息,此时线程唤醒开始执行消息。
用户按键消息。当有用户按键消息时,WMS专门处理输入消息的线程会把这个消息发送到looper主线程。
Binder中断。Binde是一个驱动设备,应用程序中包含一个Binder泽辉对应常见一个相应线程。当Binder驱动接受到消息,并派发给客户端的Binder对象后,Binder线程执行。如果在Binder消息处理中向looper主线程发送消息,此时主线程唤醒开始执行消息。
2.Android中的OOM机制
Android中运行一个OOM进程,该进程启动时会首先向Linux内核中把自己注册为一个OOM Killer。
AMS会将每一个进程oom_adj值告知Killer。
当系统内存不足时,会通知注册的OOM进程,OOMKiller就会根据oom_adj值进行内存释放。
OOMKiller是一种可选方案,对于OEM厂商可以不支持OOM。只有在不支持OOM的情况下,Android才会采用“潜规则”优先退出后台的Activity。
3.Activity退出时的内存回收过程
如上图:
1.启动Activity和按下back键都涉及Activity的销毁。
2.启动Activity时会先去暂停当前显示的Activity,当待启动Activity启动完成时回调AMS的activityIdleInternalLocked()函数。在该函数中会执行内存回收操作。
3.activityIdleInternalLocked()函数内部依次处理stop、finish状态的Activity,最后会执行到AMS的trimApplications(),在该函数中执行内存回收。
4.activityIdleInternalLocked()是执行内存回收的关键函数。
activityIdleInternalLocked()被调用的时机:
首先是Activity启动成功时ActivityThread会回调AMS的相关方法最后执行到activityIdleInternalLocked()方法。该方法内部会首先取消10s的等待启动结果定时。
在WMS回调ActivityRecord其window可见时,会回调activityIdleInternalLocked()。
在completePauseLocked()中当stop状态Activity数目大于3时会回调activityIdleInternalLocked(),这种情况一般不出现。
最后实在completePauseLocked()启动10s定时如果ActivityThread启动Activity未成功,10s时间到达会回调activityIdleInternalLocked()。
如下执行AMS.trimApplications()过程:
参考连接:
Android 7.0 ActivityManagerService(8) 进程管理相关流程分析(2) updateOomAdjLocked http://blog.csdn.net/gaugamela/article/details/53927724