本篇文章,针对java crash处理进行分析,因为项目的原因代码选择:Android 5.0。瞄了眼,高版本代码差不多,没啥太大变化。
一、Java异常
java crash日志捕获针对的是UnChecked Exception中没有被catch住的RuntimeException。
二、Java异常捕获
1)自定义Handler 实现UncaughtExceptionHandler接口
2)Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh)设置自定义Handler
3)java crash回调UncaughtExceptionHandler 的uncaughtException方法,实现奔溃信息收集,上报。
三、原理解析
这里主要就搞明白三个问题:
- 默认的UncaughtExceptionHandler何时设置?
- 应用发生java crash系统层都做了哪些工作?
- uncaughtException何时回调?
下面一个个来分析:
1)默认的UncaughtExceptionHandler何时设置?
进程启动流程zygoteInit方法中:
android-5.0.0_r7/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
...
commonInit();
...
}
private static final void commonInit() {
/* set default handler; this applies to all threads in the VM */
Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
...
}
很明显,这是应用进程创建过程中设置的默认UncaughtExceptionHandler。
2)应用发生java crash系统层都做了哪些工作?
这里接着上面继续看, Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
UncaughtHandler的实现:
private static class UncaughtHandler implements Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread t, Throwable e) {
…
// Bring up crash dialog, wait for it to be dismissed
ActivityManagerNative.getDefault().handleApplicationCrash(
mApplicationObject, new ApplicationErrorReport.CrashInfo(e));
…
finally {
// Try everything to make sure this process goes away.
Process.killProcess(Process.myPid());
System.exit(10);
}
}
}
接下来整个流程总结为一个时序图:
简单总结系统层工作内容:
- 将进程crash信息输出到/data/system/dropbox中。
- 针对进程,调整activity及其任务栈。
- 弹crash对话框。
- Process.killprocess 走binder死亡回调,清理进程及其四大组件。
3)uncaughtException何时回调?
Java进程是运行在虚拟机中的,当出现运行时异常时,虚拟机会调用:
android-5.0.0_r7/art/runtime/thread.cc
void Thread::HandleUncaughtExceptions(ScopedObjectAccess& soa) {
...
// Call the handler.
tlsPtr_.jni_env->CallVoidMethod(handler.get(),
WellKnownClasses::java_lang_Thread$UncaughtExceptionHandler_uncaughtException,
peer.get(), exception.get());
// If the handler threw, clear that exception too.
tlsPtr_.jni_env->ExceptionClear();
}
JNI回调到java的uncaughtException。