本篇文章考赛,針對(duì)java crash處理進(jìn)行分析,因?yàn)轫?xiàng)目的原因代碼選擇:Android 5.0今豆。瞄了眼嫌拣,高版本代碼差不多,沒啥太大變化呆躲。
一异逐、Java異常
java crash日志捕獲針對(duì)的是UnChecked Exception中沒有被catch住的RuntimeException。
二插掂、Java異常捕獲
1)自定義Handler 實(shí)現(xiàn)UncaughtExceptionHandler接口
2)Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh)設(shè)置自定義Handler
3)java crash回調(diào)UncaughtExceptionHandler 的uncaughtException方法灰瞻,實(shí)現(xiàn)奔潰信息收集,上報(bào)辅甥。
三酝润、原理解析
這里主要就搞明白三個(gè)問題:
- 默認(rèn)的UncaughtExceptionHandler何時(shí)設(shè)置?
- 應(yīng)用發(fā)生java crash系統(tǒng)層都做了哪些工作璃弄?
- uncaughtException何時(shí)回調(diào)要销?
下面一個(gè)個(gè)來分析:
1)默認(rèn)的UncaughtExceptionHandler何時(shí)設(shè)置?
進(jìn)程啟動(dòng)流程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());
...
}
很明顯夏块,這是應(yīng)用進(jìn)程創(chuàng)建過程中設(shè)置的默認(rèn)UncaughtExceptionHandler疏咐。
2)應(yīng)用發(fā)生java crash系統(tǒng)層都做了哪些工作?
這里接著上面繼續(xù)看脐供, Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
UncaughtHandler的實(shí)現(xiàn):
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);
}
}
}
接下來整個(gè)流程總結(jié)為一個(gè)時(shí)序圖:
簡單總結(jié)系統(tǒng)層工作內(nèi)容:
- 將進(jìn)程crash信息輸出到/data/system/dropbox中凳鬓。
- 針對(duì)進(jìn)程,調(diào)整activity及其任務(wù)棧患民。
- 彈crash對(duì)話框缩举。
- Process.killprocess 走binder死亡回調(diào),清理進(jìn)程及其四大組件。
3)uncaughtException何時(shí)回調(diào)仅孩?
Java進(jìn)程是運(yùn)行在虛擬機(jī)中的托猩,當(dāng)出現(xiàn)運(yùn)行時(shí)異常時(shí),虛擬機(jī)會(huì)調(diào)用:
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回調(diào)到j(luò)ava的uncaughtException辽慕。