程序在退出之后不会关闭进程,当应用二次启动时如果进程还在则直接使用,此处可能存在的疑问就是进程持续存在是否影响系统的执行?事实上只是当前进程处于sleep()状态,此时只占用物理内存并不会影响前台程序使用速度,我们在启动在进程后会初始化Looper对象,Looper会循环获取消息事件,当程序关闭后消息事件为空,则进程进入sleep状态,一般来说此时100个休眠进程内不会影响运行速度,当发声用户交互、定时器中断、Binder消息时会想主线程发送消息唤醒next()方法获取事件然后执行事件处理;
所有关于Android 中的OOM机制和Android对进程的处理放在后一篇文章中分析,本篇主要分析下Android内部如何管理内存机制;
由前面的学习知道,在Activity启动完成后回调ActivityThread.handleResumeActivity(),在方法的最后一句发送了一个Idler事件,此Idler事件会触发内存回收机制
Looper.myQueue().addIdleHandler(new Idler()); // 添加Idler事件
private final ArrayList<IdleHandler> mIdleHandlers = new ArrayList<IdleHandler>(); // IdlerHandler集合
public void addIdleHandler(@NonNull IdleHandler handler) {
synchronized (this) {
mIdleHandlers.add(handler); // 保存设置的Idler对象
}
}
调用MesssageQueue中的addIdleHandler()添加Idler事件,在MesssageQueue中会将所有的Idler事件都保存在mIdleHandlers的集合中,关于Idler事件的执行放在后面分析,现在一起看一下Idler类,Idler是ActivityThread的内部类,它实现了IdleHandler接口重写queueIdle(),除此之外还有GcIdler类,在添加了Idler事件后,在从MessageQueue中获取next()时,会遍历mIdleHandlers集合中的事件,获取事件后调用queueIdle()执行事件
public static interface IdleHandler {
boolean queueIdle();
}
private class Idler implements MessageQueue.IdleHandler {
@Override
public final boolean queueIdle() {
IActivityManager am = ActivityManager.getService();
am.activityIdle(a.token, a.createdConfig, stopProfiling); // 执行activityIdle(),调用activityIdleInternal()
return false;
}
}
在Idler的queueIdle()方法中,首先获取AMS对象然后调用其activityIdle()方法,这里执行到ActivityManagerService中
public final void activityIdle(IBinder token, Configuration config) {
final long origId = Binder.clearCallingIdentity();
synchronized (this) {
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
ActivityRecord r = mStackSupervisor.activityIdleInternalLocked(token, false /* fromTimeout */,
false /* processPausingActivities */, config);
}
}
Binder.restoreCallingIdentity(origId);
}
在AMS.activityIdle()中先获取ActivityStack对象后,调用mStackSupervisor.activityIdleInternalLocked()方法,本段分析先暂停在这里,之后再分析activityIdleInternalLocked()中如何回收内存;
AMS中除了上面Idler事件之外,还有一个条件会触发内存回收,在前面的学习知道在执行前一个Activity的onPause()结束后,会回调AMS的completePausedLocked(),在completePausedLocked()中会将Pause的活动添加到mStoppingActivities集合中,此时会判断当处于stopping的Activity数超过3个时会发送IDLE_NOW_MSG消息处理内存,处理消息同样执行activityIdleInternal()
void addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed) {
if (!mStackSupervisor.mStoppingActivities.contains(r)) { // 加入停止活动集合
mStackSupervisor.mStoppingActivities.add(r);
}
boolean forceIdle = mStackSupervisor.mStoppingActivities.size() > MAX_STOPPING_TO_FORCE
|| (r.frontOfTask && mTaskHistory.size() <= 1);
if (scheduleIdle || forceIdle) {
if (!idleDelayed) {
mStackSupervisor.scheduleIdleLocked(); //数量大于3发送IDLE事件执行内存回收,销毁Stop集合中的Activity
} else {
mStackSupervisor.scheduleIdleTimeoutLocked(r);
}
} else {
checkReadyForSleep();
}
}
void scheduleIdleTimeoutLocked(ActivityRecord next) {
Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
}
final void scheduleIdleLocked() {
mHandler.sendEmptyMessage(IDLE_NOW_MSG);
}
scheduleIdleTimeoutLocked()和scheduleIdleLocked()都只是发送Handler事件,在处理相应的事件时都会调用activityIdleInternal()方法,在activityIdleInternal中直接调用activityIdleInternalLocked();
// scheduleIdleLocked()发送Handler事件,执行事件的回收
case IDLE_TIMEOUT_MSG: {
activityIdleInternal((ActivityRecord) msg.obj,
true /* processPausingActivities */);
} break;
case IDLE_NOW_MSG: {
activityIdleInternal((ActivityRecord) msg.obj,
false /* processPausingActivities */);
} break;
final void activityIdleInternalLocked(IBinder token, boolean fromTimeout,Configuration config) {
ArrayList<ActivityRecord> stops = null; // 保存ActivityRecord集合
ArrayList<ActivityRecord> finishes = null;
if (token != null) {
mHandler.removeMessages(IDLE_TIMEOUT_MSG, token); // 移除超时消息,避免多次重复执行
}
int index = indexOfTokenLocked(token);
ActivityRecord r = (ActivityRecord)mHistory.get(index); // 获取当前token对应的ActivityRecord
r.idle = true;
mService.scheduleAppGcsLocked(); // 1、发送Handler事件执行客户端的内存回收
stops = processStoppingActivitiesLocked(true); // 2、将mStoppingActivity集合保存到stops,清空mStoppingActivity集合
if ((NF=mFinishingActivities.size()) > 0) {
finishes = new ArrayList<ActivityRecord>(mFinishingActivities); // 3、将mFinishingActivity保存到finishes集合中
mFinishingActivities.clear(); // 清空集合
}
for (i=0; i<NS; i++) {
2807 ActivityRecord r = (ActivityRecord)stops.get(i);
2808 synchronized (mService) {
2809 if (r.finishing) {
2810 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY); // 对与finish=true的,直接结束Activity
2811 } else {
2812 stopActivityLocked(r); // 4、执行stopping集合中Activity的onStop()
2813 }
2814 }
2815 }
2819 for (i=0; i<NF; i++) {
2820 ActivityRecord r = (ActivityRecord)finishes.get(i);
2821 synchronized (mService) {
2822 destroyActivityLocked(r, true);// 5、直接destroy() 所有的Finishing的Activity
2823 }
2824 }
}
mService.trimApplications(); // 6、执行真正的内存回收或杀死进程
在activityIdleInternalLocked()中主要执行以下操作:
final void scheduleAppGcLocked(ProcessRecord app) {
11917 long now = SystemClock.uptimeMillis();
11918 if ((app.lastRequestedGc+GC_MIN_INTERVAL) > now) { // 1判断上次执行GC时间和现在时间慢不满足最小GC时间间隔
11919 return;
11920 }
11921 if (!mProcessesToGc.contains(app)) {
11922 addProcessToGcListLocked(app); // 2、
11923 scheduleAppGcsLocked(); // 3、
11924 }
11925 }
在scheduleAppGcLocked()中首先获取上一次执行GC的时间和当前时间,计算是否满足最小GC时间间隔,如果不满足则直接return,然后将app进程添加到将要执行GC的 mProcessToGC集合中保存,发送延时信息,通知进程执行GC
final void addProcessToGcListLocked(ProcessRecord proc) {
11897 boolean added = false;
11898 for (int i=mProcessesToGc.size()-1; i>=0; i--) {
11899 if (mProcessesToGc.get(i).lastRequestedGc < // 适当的位置
11900 proc.lastRequestedGc) {
11901 added = true;
11902 mProcessesToGc.add(i+1, proc);
11903 break;
11904 }
11905 }
11906 if (!added) {
11907 mProcessesToGc.add(0, proc); // 如果都没有,直接插在第一个位置
11908 }
11909 }
在addProcessToGcListLocked()中按照mProcessToGc中每个app上次GC的时间排序,将app进程插入到集合中,如果此时集合中没有对象则直接保存数据;
final void scheduleAppGcsLocked() {
11875 mHandler.removeMessages(GC_BACKGROUND_PROCESSES_MSG); // 移除之前的消息事件
11876
11877 if (mProcessesToGc.size() > 0) {
11879 ProcessRecord proc = mProcessesToGc.get(0); //从mProcessToGc中去除第一个进程proc
11880 Message msg = mHandler.obtainMessage(GC_BACKGROUND_PROCESSES_MSG);
11881
11882 long when = mProcessesToGc.get(0).lastRequestedGc + GC_MIN_INTERVAL; // 设置延迟发送时间
11883 long now = SystemClock.uptimeMillis();
11884 if (when < (now+GC_TIMEOUT)) {
11885 when = now + GC_TIMEOUT; // 计算或修正时间
11886 }
11887 mHandler.sendMessageAtTime(msg, when); // 发送请求GC的消息
11888 }
11889 }
在scheduleAppGcsLocked()中从mProcessesToGc集合中取出第一个进程,计算并设置发送事件的时间最后发送事件,在Handler接收到事件后调用performAppGcsIfAppropriateLocked()方法处理事件;
final void performAppGcsIfAppropriateLocked() {
11863 if (canGcNowLocked()) { // 判断当前是否适合执行GC操作
11864 performAppGcsLocked(); // 执行GC
11865 return;
11866 }
11868 scheduleAppGcsLocked(); //在不适合的情况下,再次发送延时消息
11869 }
private final boolean canGcNowLocked() {
11820 return mParallelBroadcasts.size() == 0 // 判断当前是否有正在执行的广播
11821 && mOrderedBroadcasts.size() == 0
// 判断是否处于sleep状态或具有正在交互的Activity且Activity处于idle状态
11822 && (mSleeping || (mMainStack.mResumedActivity != null && mMainStack.mResumedActivity.idle));
11824 }
在performAppGcsIfAppropriateLocked()中首先判断当前是否适合执行GC操作,主要检查是否有正在发送的广播、进程是否处于sleep、是否有正在交互的活动等,对于不能直接执行GC的继续发送延时事件,对于可执行的调用performAppGcsLocked()
final void performAppGcsLocked() {
11831 final int N = mProcessesToGc.size();
11835 if (canGcNowLocked()) {
11836 while (mProcessesToGc.size() > 0) { // 循环便利mProcessToGc集合中的每个进程
11837 ProcessRecord proc = mProcessesToGc.remove(0);
11838 if (proc.curRawAdj > PERCEPTIBLE_APP_ADJ || proc.reportLowMemory) { // 执行条件
11839 if ((proc.lastRequestedGc+GC_MIN_INTERVAL) <= SystemClock.uptimeMillis()) { // 执行时间
11843 performAppGcLocked(proc); // 执行回收内存
11844 scheduleAppGcsLocked(); //再次发送延迟事件,每次只处理一个进程
11845 return; // 直接return
11846 } else {
11849 addProcessToGcListLocked(proc);
11850 break;
11851 }
11852 }
11853 }
11855 scheduleAppGcsLocked(); // 发送延迟事件
11856 }
11857 }
在performAppGcsLocked()中主要从mProcessesToGc集合中取出第一个进程,然后调用performAppGcLocked()执行内存回收操作,在操作完成后再次发送延时事件,从这里可以看出GC操作每次只执行一个进程,且执行一次后会延时到下一次执行;
final void performAppGcLocked(ProcessRecord app) {
11801 try {
11802 app.lastRequestedGc = SystemClock.uptimeMillis(); // 保存本次执行GC的时间
11803 if (app.thread != null) {
11804 if (app.reportLowMemory) { //低内存状态
11805 app.reportLowMemory = false;
11806 app.thread.scheduleLowMemory(); // 内存低导致内存释放
11807 } else {
11808 app.thread.processInBackground(); //处理背景模式释放Binder内存
11809 }
11810 }
11811 }
11814 }
在performAppGcLocked()中首先保存当前GC的时间,然后回调ApplicaitonThread的scheduleLowMemory()方法,同样方法会执行到ActivityThread.scheduleLowMemory()中,scheduleLowMemory中调用Handler发送LOW_MEMORY消息,Handler收到信息后执行handleLowMemory();
final void handleLowMemory() {
3097 ArrayList<ComponentCallbacks> callbacks = new ArrayList<ComponentCallbacks>();
3099
3100 synchronized (mPackages) {
// 从mActivites集合中查找没有Finfish和Paused的Activity、Service、Provider、Application等
3101 callbacks = collectComponentCallbacksLocked(true, null);
3102 }
3103
3104 final int N = callbacks.size();
3105 for (int i=0; i<N; i++) {
3106 callbacks.get(i).onLowMemory(); // 回到所有Activity的onLowMemory()
3107 }
3110 if (Process.myUid() != Process.SYSTEM_UID) {
3111 int sqliteReleased = SQLiteDatabase.releaseMemory(); // 释放SQLite内存
3113 }
3116 Canvas.freeCaches(); // 释放Canvas
Canvas.freeTextLayoutCaches(); // 布局引擎释放内存
3118 BinderInternal.forceGc("mem”); // 释放Binder
3119 }
在handleLowMemory()中主要执行以下几个内存释放操作:
for (int i = 0; i < NS; i++) {
r = stops.get(i);
final ActivityStack stack = r.getStack();
if (stack != null) {
if (r.finishing) {
stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false,
"activityIdleInternalLocked");
} else {
stack.stopActivityLocked(r);
}
}
}
在处理mStopping集合中保存的活动时,此时活动都处于Paused状态,在获取到ActivityRecord之后会判断其finishing属性,finishing为true表示需要销毁此对象,然后调用ActivityStack.finishCurrentActivityLocked(),对于不想销毁的执行ActivityStack.stopActivityLocked()方法;
// 删除集合中的此Record信息
mStackSupervisor.mStoppingActivities.remove(r);
mStackSupervisor.mGoingToSleepActivities.remove(r);
mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(r);
if (mode == FINISH_IMMEDIATELY
|| (prevState == PAUSED
&& (mode == FINISH_AFTER_PAUSE || inPinnedWindowingMode()))
|| finishingActivityInNonFocusedStack
|| prevState == STOPPING
|| prevState == STOPPED
|| prevState == ActivityState.INITIALIZING) {
r.makeFinishingLocked();
boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm:" + reason);
if (finishingActivityInNonFocusedStack) {
mStackSupervisor.ensureVisibilityAndConfig(next, mDisplayId,
false /* markFrozenIfConfigChanged */, true /* deferResume */);
}
if (activityRemoved) {
mStackSupervisor.resumeFocusedStackTopActivityLocked();
}
return activityRemoved ? null : r;
}
在finishCurrentActivityLocked()中首先从保存信息的集合中移除信息面,因为此活动即将被销毁,然后判断当前活动的状态并调用ActivityRecord.makeFinishingLocked(),最后调用destroyActivityLocked()销毁Activity,关于destroyActivityLocked()放在之后分析,在销毁活动之后又调用resumeFocusedStackTopActivityLocked()方法显示栈顶的活动;
if (!r.visible) {
r.setVisible(false);
}
adjustFocusedActivityStack(r, "stopActivity"); //1
//2
mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,
StopActivityItem.obtain(r.visible, r.configChangeFlags));
//3
Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r);
mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
在stopActivityLocked()中主要执行三件事:
for (int i = 0; i < NF; i++) {
r = finishes.get(i);
final ActivityStack stack = r.getStack();
if (stack != null) {
activityRemoved |= stack.destroyActivityLocked(r, true, "finish-idle");
}
}
cleanUpActivityLocked(r, false, false);
final boolean hadApp = r.app != null; // 1、
if (hadApp) {
r.app.activities.remove(r); //2、
mService.getLifecycleManager().scheduleTransaction(r.app.thread, r.appToken,
DestroyActivityItem.obtain(r.finishing, r.configChangeFlags)); //3、
Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG, r); //4、
mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
}else {
if (r.finishing) {
removeActivityFromHistoryLocked(r, reason + " hadNoApp");
removedFromHistory = true; //5、
} else {
r.setState(DESTROYED, "destroyActivityLocked. not finishing and had no app"); //6、
r.app = null;
}
}
if (!mLRUActivities.remove(r) && hadApp) { //7、
Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
}
在destroyActivityLocked()中执行:
总结以下:在AMS对Activity调度管理中包含着对程序内存的处理,在resume完目标Activity后即表示活动已经启动完毕,之后会添加内存回收相关的Idler事件,在事件执行时会触发Activity的低内存状态,通知应用程序释放内存,客户端在收到消息后会释放程序内存、数据库内存、Binder内存等,在处理内存之后AMS会对目前Stopping和finishing中的活动,执行对应的stop()和finish()方法;