在这篇博客中,我们来看一下AMS处理App crash时涉及到的主要流程。
一、设置异常处理器
在Android平台中,应用进程fork出来后会为虚拟机设置一个未截获异常处理器,
即在程序运行时,如果有任何一个线程抛出了未被截获的异常,
那么该异常最终会抛给未截获异常处理器处理。
我们首先看看Android N中设置异常处理器的这部分代码。
在ZygoteInit.java的runSelectLoop中:
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
...........
while (true) {
..........
for (int i = pollFds.length - 1; i >= 0; --i) {
..........
if (i == 0) {
//zygote中的server socket收到消息后,建立起ZygoteConnection
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
//ZygoteConnection建立后,收到消息调用自己的runOnce函数
boolean done = peers.get(i).runOnce();
.............
}
}
}
}
我们知道zygote启动后,会在自己的进程中定义一个server socket,专门接收创建进程的消息。
如上面的代码所示,收到创建进程的消息后,zygote会创建出ZygoteConnection,并调用其runOnce函数:
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
...............
try {
...........
//fork出子进程
pid = Zygote.forkAndSpecialize(.......);
} catch (ErrnoException ex) {
............
} catch (IllegalArgumentException ex) {
...........
} catch (ZygoteSecurityException ex) {
..........
}
try {
if (pid == 0) {
........
//进程fork成功后,进行处理
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
........
} else {
...........
}
} finally {
..........
}
}
我们跟进一下handleChildProc函数:
private void handleChildProc(......) {
............
if (parsedArgs.invokeWith != null) {
..........
} else {
//进入到RuntimeInit中的zygoteInit函数
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, null /* classLoader */);
}
}
顺着流程看一看RuntimeInit中的zygoteInit函数:
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
............
//跟进commonInit
commonInit();
............
}
private static final void commonInit() {
...........
/* set default handler; this applies to all threads in the VM */
//到达目的地!
Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
...........
}
从上面的代码可以看出,fork出进程后,将在进程commonInit的阶段设置异常处理器UncaughtHandler。
二、异常处理的流程
1、UncaughtHandler的异常处理
接下来我们看看UncaughtHandler如何处理未被捕获的异常。
private static class UncaughtHandler implements Thread.UncaughtExceptionHandler {
public