飞书链接
一、ActivityManager.java killBackgroundProcesses
该方法须在manifest文件中申明相关权限。调用该方法杀掉后台进程后,系统会根据一系列的判断来决定是否有必要重新启动该进程。不会杀掉有persistent 属性的进程。不会杀掉system级别权限的进程。被杀掉的进程当前的ADJ级别要大于SERVICE_ADJ。电视开发中,在杀死某些直播软件后起声音也可能不会停止。
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
activityManager.killBackgroundProcesses(包名);
permission :<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
Android 中调用位置较少,主要是 低内存情况下调用 和 提供APP使用。
ADB 调用 adb shell am kill packagename
android/frameworks/base/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
case "kill":
return runKill(pw);
case "kill-all":
return runKillAll(pw);
int runKill(PrintWriter pw) throws RemoteException {
int userId = UserHandle.USER_ALL;
String opt;
while ((opt=getNextOption()) != null) {
if (opt.equals("--user")) {
userId = UserHandle.parseUserArg(getNextArgRequired());
} else {
getErrPrintWriter().println("Error: Unknown option: " + opt);
return -1;
}
}
mInterface.killBackgroundProcesses(getNextArgRequired(), userId);
return 0;
}
int runKillAll(PrintWriter pw) throws RemoteException {
mInterface.killAllBackgroundProcesses();
return 0;
}
最终实现 (默认allowRestart 值为 true)
Process.killProcessQuiet(pid); ProcessList.killProcessGroup(uid, pid);
android/frameworks/base/services/core/java/com/android/server/am/ProcessRecord.java
void kill(String reason, @Reason int reasonCode, @SubReason int subReason, boolean noisy) {
if (!killedByAm) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill");
if (mService != null && (noisy || info.uid == mService.mCurOomAdjUid)) {
mService.reportUidInfoMessageLocked(TAG,
"Killing " + toShortString() + " (adj " + setAdj + "): " + reason,
info.uid);
}
if (pid > 0) {
mService.mProcessList.noteAppKill(this, reasonCode, subReason, reason);
EventLog.writeEvent(EventLogTags.AM_KILL, userId, pid, processName, setAdj, reason);
Process.killProcessQuiet(pid);
ProcessList.killProcessGroup(uid, pid);
} else {
pendingStart = false;
}
if (!mPersistent) {
killed = true;
killedByAm = true;
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
二、ActivityManager.java forceStopPackage
拥有相同uid的进程都会被杀掉。运行其中的服务都是停止掉,activity都会移除掉,应用不会重新启动。须在manifest文件中申明相关的权限。
ActivityManager mAm = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
mAm.forceStopPackage(包名);
permission :<uses-permission android:name="android.permission.FORCE_STOP_PACKAGES"/>
Android 中这个的使用场景就多了。常见的有:
Lowmemkiller 调用
public void doLmkForceStop(int pid) {
Slog.d(TAG, "doLmkForceStop pid=" + pid);
......
mService.forceStopPackage(pkgName, UserHandle.USER_CURRENT);
Slog.i(TAG, "force stop pkg:" + pkgName + ", pid:" + pid
+ " (adj " + pr.setAdj + ") has done.");
}
ADB 调用 adb shell am force-stop packagename
android/frameworks/base/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
case "force-stop":
return runForceStop(pw);
int runForceStop(PrintWriter pw) throws RemoteException {
int userId = UserHandle.USER_ALL;
String opt;
while ((opt = getNextOption()) != null) {
if (opt.equals("--user")) {
userId = UserHandle.parseUserArg(getNextArgRequired());
} else {
getErrPrintWriter().println("Error: Unknown option: " + opt);
return -1;
}
}
mInterface.forceStopPackage(getNextArgRequired(), userId);
return 0;
}
最终实现 同为 下面, 区别在于 allowRestart 这里是 false
Process.killProcessQuiet(pid); ProcessList.killProcessGroup(uid, pid);
三、Process.java KillProcess
最终调用的是Linux API kill()方法发送SIGKILL信号。理论上该接口允许我们凭借pid号杀掉任意进程,但Kernel 仍然会对调用者进行标准的检查已判断哪些进程允许被调用者杀掉。以下几种情况可以调用此方法:
1、调用者自杀。
2、被杀进程是由调用者创建。
3、共享相同UID的进程能够互杀。
此方法在Google原生代码中多用于Framework 层AM服务,单个应用运用此方法较少。大多数的用法为进程自我销毁,基本没有看到运用此方法杀非本进程的用法。
android.os.Process.killProcess(android.os.Process.myPid());
Android 中实例:
很常见的 Thread.UncaughtExceptionHandler ,
下面是 framework 中默认实现 UncaughtExceptionHandler 的 KillApplicationHandler 的代码。
可以看出,异常退出时,是需要 kill + exit 的。
android/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
@Override
public void uncaughtException(Thread t, Throwable e) {
try {
ensureLogging(t, e);
// Don't re-enter -- avoid infinite loops if crash-reporting crashes.
if (mCrashing) return;
mCrashing = true;
// Try to end profiling. If a profiler is running at this point, and we kill the
// process (below), the in-memory buffer will be lost. So try to stop, which will
// flush the buffer. (This makes method trace profiling useful to debug crashes.)
if (ActivityThread.currentActivityThread() != null) {
ActivityThread.currentActivityThread().stopProfiling();
}
// Bring up crash dialog, wait for it to be dismissed
ActivityManager.getService().handleApplicationCrash(
mApplicationObject, new ApplicationErrorReport.ParcelableCrashInfo(e));
} catch (Throwable t2) {
if (t2 instanceof DeadObjectException) {
// System process is dead; ignore
} else {
try {
Clog_e(TAG, "Error reporting crash", t2);
} catch (Throwable t3) {
// Even Clog_e() fails! Oh well.
}
}
} finally {
// Try everything to make sure this process goes away.
Process.killProcess(Process.myPid());
System.exit(10);
}
}
四、System.java exit
导致虚拟机停止运行并且该应用退出,所带参数如果非0,则说明是非正常退出。此方法在Google原生代码中多用于cts类和tool类,即(J2SE代码中对应的main方法中调用此方法退出),单个应用程序基本没有运用此方法。平台偶尔有使用此方法完成应用启动后的退出。但貌似该方法会引起findBug问题。不建议使用。
System.exit(0);
Android 中实例:
android/frameworks/base/cmds/sm/src/com/android/commands/sm/Sm.java
public static void main(String[] args) {
boolean success = false;
try {
new Sm().run(args);
success = true;
} catch (Exception e) {
if (e instanceof IllegalArgumentException) {
showUsage();
System.exit(1);
}
Log.e(TAG, "Error", e);
System.err.println("Error: " + e);
}
System.exit(success ? 0 : 1);
}
五、Runtime.java exit
其实system.java 的 exit方法的具体实现即为: Runtime.getRuntime().exit(code);
private static final int MSG_DELAY_EXIT_APP = 0;
private static Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case MSG_DELAY_EXIT_APP:
Runtime.getRuntime().exit(0);
break;
}
}
};
mHandler.sendEmptyMessageDelayed(MSG_DELAY_EXIT_APP, 4000);