killProcess 和 exit 的区别

Process.killProcess(pid)

最终执行系统调用 kill

class Process {
    public static final int SIGNAL_KILL = 9;

    public static final void killProcess(int pid) {
        sendSignal(pid, SIGNAL_KILL);
    }

    public static final native void sendSignal(int pid, int signal);
}
// android_util_Process.cpp
void android_os_Process_sendSignal(JNIEnv* env, jobject clazz, jint pid, jint sig)
{
    if (pid > 0) {
        ALOGI("Sending signal. PID: %" PRId32 " SIG: %" PRId32, pid, sig);
        kill(pid, sig);
    }
}

signal(信号)

信号 是一个古老的、异步的 IPC 机制,一个进程可以给另一个进程发送信号(kill),收到信号(SIGxxx)的进程会暂停并进入相应的信号处理程序(Signal Handlers),信号处理程序是可以配置的

kill -s sig pid
kill(pid, sig)

// 自定义信号处理程序
// handler 可以是:SIG_IGN 忽略此信号,SIG_DFL 设置默认的信号处理程序,函数地址
// SIGKILL 和 SIGSTOP 是不可以忽略和自定义的
signal(signum, handler)

常见的信号

Singal Number Default Action Desc
SIGKILL 9 Terminate (core dump) Kill (cannot be caught or ignored)
SIGSEGV 11 Terminate (core dump) Invalid memory reference
SIGINT 2 Terminate Terminal interrupt signal,常见于在控制台由 Ctrl-C 触发
SIGSTOP Stop Stop executing (cannot be caught or ignored),常见于在控制台由 Ctrl-Z 触发

System.exit(status)

退出 VM 回到 native 代码,能够保证 shutdown hook 执行完,native 代码甚至可以重新进入 VM 或者做其他的事,进程没有被杀死,其他 native thread 也在正常运行

class System {
    public static void exit(int status) {
        Runtime.getRuntime().exit(status);
    }
}

class Runtime {
    public void exit(int status) {
        // Make sure we don't try this several times
        synchronized(this) {
            if (!shuttingDown) {
                shuttingDown = true;

                Thread[] hooks;
                synchronized (shutdownHooks) {
                    // create a copy of the hooks
                    hooks = new Thread[shutdownHooks.size()];
                    shutdownHooks.toArray(hooks);
                }

                // Start all shutdown hooks concurrently
                for (Thread hook : hooks) {
                    hook.start();
                }

                // Wait for all shutdown hooks to finish
                for (Thread hook : hooks) {
                    try {
                        hook.join();
                    } catch (InterruptedException ex) {
                        // Ignore, since we are at VM shutdown.
                    }
                }

                // Ensure finalization on exit, if requested
                if (finalizeOnExit) {
                    runFinalization();
                }

                // Get out of here finally...
                nativeExit(status);
            }
        }
    }
}

shutdown hook

通过 Runtime.addShutdownHook(Thread) 添加的任务确实可以在 System.exit(status) 时被执行,但就像 Uncaught Exception Handling 里描述的那样,主线程退出 VM 后虽然没有结束(在等待 shutdown hook 执行完毕),但它也不再消费分发过来的 input 事件导致出现 ANR 对话框,然后被用户杀死 app process,当然在进程被杀死前 shutdown hook 也有跟 uncaught exception handler 差不多长的生存时间