2.4 进程垃圾回收
2.4.1 进程回收
MyActivityManagerService的runProcessGC主要逻辑如下,
1,调用ActivityManager的getRunningAppProcesses方法获取当前宿主框架的运行进程,
ActivityManager am = (ActivityManager) mHostContext.getSystemService(Context.ACTIVITY_SERVICE);
if (am == null) {
return;
}
List<RunningAppProcessInfo> infos = am.getRunningAppProcesses();
List<RunningAppProcessInfo> myInfos = new ArrayList<RunningAppProcessInfo>();
当然, IactivityManagerHookHandle的内部类getRunningAppProcesses的afterInvoke方法在此就不论述了。
2, 如果是插件进程(非宿主进程), 按进程优先级排序,调用doGc方法杀掉优先级较低的进程。
Collections.sort(myInfos, sProcessComparator);
for (RunningAppProcessInfo myInfo : myInfos) {
if (myInfo.importance == RunningAppProcessInfo.IMPORTANCE_GONE) {
doGc(myInfo);
} else if (myInfo.importance == RunningAppProcessInfo.IMPORTANCE_EMPTY) {
doGc(myInfo);
} else if (myInfo.importance == RunningAppProcessInfo.IMPORTANCE_BACKGROUND) {
doGc(myInfo);
} else if (myInfo.importance == RunningAppProcessInfo.IMPORTANCE_SERVICE) {
doGc(myInfo);
} /*else if (myInfo.importance == RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE) {
//杀死进程,不能保存状态。但是关我什么事?
}*/ else if (myInfo.importance == RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE) {
//杀死进程
} else if (myInfo.importance == RunningAppProcessInfo.IMPORTANCE_VISIBLE) {
//看得见
} else if (myInfo.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
//前台进程。
}
}
doGc方法的逻辑如下,
1, 首先kill没有任何activity、service、provider的空进程
int activityCount = mRunningProcessList.getActivityCountByPid(myInfo.pid);
int serviceCount = mRunningProcessList.getServiceCountByPid(myInfo.pid);
int providerCount = mRunningProcessList.getProviderCountByPid(myInfo.pid);
if (activityCount <= 0 && serviceCount <= 0 && providerCount <= 0) {
//杀死空进程。
Log.i(TAG, "doGc kill process(pid=%s,uid=%s processName=%s)", myInfo.pid, myInfo.uid, myInfo.processName);
try {
android.os.Process.killProcess(myInfo.pid);
} catch (Throwable e) {
Log.e(TAG, "error on killProcess", e);
}
直接调用Process的killProcess方法kill进程。
2, 对于没有activity,只有service的进程,获取该进程的所有服务,调用stopSelf()停掉服务
else if (activityCount <= 0 && serviceCount > 0 /*&& !mRunningProcessList.isPersistentApplication(myInfo.pid)*/) {
List<String> names = mRunningProcessList.getStubServiceByPid(myInfo.pid);
if (names != null && names.size() > 0) {
for (String name : names) {
Intent service = new Intent();
service.setClassName(mHostContext.getPackageName(), name);
AbstractServiceStub.startKillService(mHostContext, service);
Log.i(TAG, "doGc kill process(pid=%s,uid=%s processName=%s) service=%s", myInfo.pid, myInfo.uid, myInfo.processName, service);
}
}
}
调用AbstractServiceStub 的startKillService 方法Kill进程的service。
2.4.2 service回收
AbstractServiceStub的startKillService方法如下,
public static void startKillService(Context context, Intent service) {
service.putExtra("ActionKillSelf", true);
context.startService(service);
}
也是启动该服务,只是多了一个string信息。
AbstractServiceStub的onStart方法对该信息处理如下,
if (intent.getBooleanExtra("ActionKillSelf", false)) {
startKillSelf();
if (!ServcesManager.getDefault().hasServiceRunning()) {
stopSelf(startId);
boolean stopService = getApplication().stopService(intent);
•••
首先看startKillSelf,该方法如下,
private void startKillSelf() {
if (isRunning) {
try {
new Thread() {
@Override
public void run() {
synchronized (sLock) {
try {
sLock.wait();
} catch (Exception e) {
}
}
Log.i(TAG, "doGc Kill Process(pid=%s,uid=%s has exit) for %s 2", android.os.Process.myPid(), android.os.Process.myUid(), getClass().getSimpleName());
android.os.Process.killProcess(android.os.Process.myPid());
}
}.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
开启了一个子线程,并且加锁等待,如果持有线程锁,就会调用Process的killProcess方法杀死进程。
那什么时候持有锁的地方会释放锁呢?在onDestroy方法当中,
public void onDestroy() {
try {
mCreator.onDestroy();
} catch (Exception e) {
handleException(e);
}
super.onDestroy();
isRunning = false;
try {
synchronized (sLock) {
sLock.notifyAll();
}
} catch (Exception e) {
}
}
当服务被回收时,就会kill服务所在的进程。
Service的stopSelf方法如下,
public final void stopSelf(int startId) {
if (mActivityManager == null) {
return;
}
try {
mActivityManager.stopServiceToken(
new ComponentName(this, mClassName), mToken, startId);
} catch (RemoteException ex) {
}
}
调用AMS的stopServiceToken 方法停止服务。当然会调用IactivityManagerHookHandle的内部类stopServiceToken的beforeInvoke方法,
前面已论述过程,在此就不论述了。