应用程序crash在开发过程中还是很常见的,本文主要是从源码的角度去跟踪下Android对于crash的处理流程。App crash的全称:Application crash。而Crash又分为:native crash和framework crash(包含App Crash)。我们在平时开发的时候对于可能有异常的地方,一般都是用try-catch语句去catch 异常信息,但当没有有效的catch住的时候,就会导致应用crash,此时系统就会进行捕获,并进入到crash的流程。
在《从源码角度看Android系统Zygote进程启动过程》一文中可知:system_server进程和上层应用程序的进程都是Zygote进程fork来的,而在这些进程创建的时候会设置未捕获异常的处理器,当系统中有未捕获的异常时候,就会交给异常器去处理。
无论是system_server进程还是应用程序进程都会在创建的过程中调用RuntimeInit.java的commonInit方法去做一些通用的初始化操作,其中就有设置默认的未捕捉异常处理器UncaughtHandler。
备注:本文将结合Android6.0的源码深入理解Android Crash处理流程
1. Android Crash 处理流程
下面以RuntimeInit.java的commonInit方法为起点对Crash流程进行跟踪分析。
1.1 RuntimeInit.java—>commonInit方法
代码路径:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
深入到commonInit的方法中:
private static final void commonInit() {
if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");
//设置默认的未捕获异常处理器
Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler()); //注释1
...省略...
}
注释解析:
- 注释1处就是给要创建的进程设置未捕获异常处理器。setDefaultUncaughtExceptionHandler是将异常处理器的handler对象赋给Thread的成员变量。
下面继续跟踪看UncaughtHandler对象实例化的过程!!!
1.2 RuntimeInit.java—>静态内部类UncaughtHandler
代码路径:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
深入到静态内部类UncaughtHandler中:
private static class UncaughtHandler implements Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread t, Throwable e) {
try {
//确保crash过程不会重复进入
if (mCrashing) return;
mCrashing = true;
//判断是否为系统进程
if (mApplicationObject == null) {
//系统进程
Clog_e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e); //注释1
} else {
//普通进程
// 注释2
StringBuilder message = new StringBuilder();
message.append("FATAL EXCEPTION: ").append(t.getName()).append("\n");
final String processName = ActivityThread.currentProcessName();
if (processName != null) {
message.append("Process: ").append(processName).append(", ");
}
message.append("PID: ").append(Process.myPid());
Clog_e(TAG, message.toString(), e);
}
// 注释3
ActivityManagerNative.getDefault().handleApplicationCrash(
mApplicationObject, new ApplicationErrorReport.CrashInfo(e));
} catch (Throwable t2) {
try {
Clog_e(TAG, "Error reporting crash", t2);
} catch (Throwable t3) {
// Even Clog_e() fails! Oh well.
}
} finally {
// 注释4
Process.killProcess(Process.myPid());
System.exit(10);
}
}
}
注释解析:
-
注释1处当是系统进程Crash信息时:
-
开头是: *** FATAL EXCEPTION IN SYSTEM PROCESS:[线程名]
-
输出发生Crash时的调用栈信息
-
-
注释2处当是普通应用进程时:
-
开头是:FATAL EXCEPTION:[线程名]
-
然后是:Process:[进程名],PID:[进程id]
-
输出发生Crash时的调用栈信息
-
-
注释3处是启动Crash的弹框。而ActivityManagerNative.getDefault()返回的是ActivityManagerProxy(简称AMP),AMP经过binder调用最后会交给ActivityManagerService(简称AMS),即Crash的弹框最终调用的是AMS的handleApplicationCrash方法。其中传入的参数new ApplicationErrorReport.CrashInfo(e)的作