異常?崩潰?不是應該的嗎?這....
看到這個問題是不是這樣 ->
1、爲什麼發生Exception後應用會發生奔潰?
當我們的應用發生未捕獲異常後程序會回調到Thread 的dispatchUncaughtException方法,如下:
//Thread.java
public final void dispatchUncaughtException(Throwable e) {
...省略部分代碼
// END Android-added: uncaughtExceptionPreHandler for use by platform.
getUncaughtExceptionHandler().uncaughtException(this, e);
}
然後通過getUncaughtExceptionHandler去獲取UncaughtExceptionHandler對象
//Thread.java
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
return uncaughtExceptionHandler != null ? uncaughtExceptionHandler : group;
}
正常我們都沒有設置UncaughtExceptionHandler,所有最後會將異常交給group(ThreadGroup)的uncaughtException進行處理,如下:
//ThreadGroup.java
public void uncaughtException(Thread t, Throwable e) {
if (parent != null) {
parent.uncaughtException(t, e);
} else {
Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler();
...省略部分代碼
}
}
在uncaughtException中,父類不等於null,則交由父類處理,否則會通過Thread.getDefaultUncaughtExceptionHandler();獲取一個默認的UncaughtExceptionHandler來處理這個異常。
//Thread.java
public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){
return defaultUncaughtExceptionHandler;
}
那麼Thread類的defaultUncaughtExceptionHandler是什麼時候被賦值的呢?
是在RuntimeInit類的入口函數main函數中的commonInit方法:
//RuntimeInit.java
public static final void main(String[] argv) {
...
commonInit();
...
}
//RuntimeInit.java
protected static final void commonInit() {
...
Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler));
...
}
這個給Thread的setDefaultUncaughtExceptionHandler設置了一個KillApplicationHandler的handler。KillApplicationHandler的uncaughtException方法如下:
//KillApplicationHandler.java
public void uncaughtException(Thread t, Throwable e) {
try {
// Bring up crash dialog, wait for it to be dismissed
ActivityManager.getService().handleApplicationCrash(
mApplicationObject, new ApplicationErrorReport.ParcelableCrashInfo(e));
} catch (Throwable t2) {
...
} finally {
// Try everything to make sure this process goes away.
Process.killProcess(Process.myPid());
System.exit(10);
}
}
在try代碼塊中調用了ActivityManagerService的handleApplicationCrash方法,在這裏去寫本地日誌和彈出異常dialog。
最後在finally代碼塊中調用了Process.killProcess(Process.myPid()) 和 System.exit(10) 殺掉進程。
至此,當應用發生未捕獲異常崩潰時的流程就結束了。
上文中提到我們沒有設置UncaughtExceptionHandler,其實現在很多應用也會設置通過setUncaughtExceptionHandler來設置UncaughtExceptionHandler。用於捕獲異常,在回調裏可以將異常日誌進行整理,然後在合適的時機回傳到服務器。
那麼setUncaughtExceptionHandler和setDefaultUncaughtExceptionHandler有什麼區別呢?
setUncaughtExceptionHandler :設置上文中的UncaughtExceptionHandler,只有當前線程生效。
setDefaultUncaughtExceptionHandler,設置defaultUncaughtExceptionHandler,對所有線程生效。
2、native_crash 奔潰怎麼監控?
這裏簡單提下native的崩潰。
通過NativeCrashListener線程去監控。NativeCrashListener繼承了Thread。
那麼NativeCrashListener是什麼時候開啓監控的?
通過ActivityManagerService中的startObservingNativeCrashes方法開啓監控。
具體邏輯:通過socket去監聽文件描述符,之後進入阻塞狀態,直到發生native異常,會向文件描述符中寫入數據,此時,被喚醒,然後通過consumeNativeCrashData方法通過IO流去讀取奔潰信息。在通過NativeCrashReport方法進行數據包裝,包裝爲CrashInfo,然後又跳轉到了ActivityManagerService中的handleApplicationCrashInner函數中進行處理。和上文中邏輯一樣。
微信掃一掃,關注我的公衆號
本文分享自微信公衆號 - Android開發之旅(AndroidDevTour)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。