According to the Java API documentation, when a thread is about to terminate due to an uncaught exception, the Java Virtual Machine will query the thread for its UncaughtExceptionHandler using Thread.getUncaughtExceptionHandler() and will invoke the handler's uncaughtException method, passing the thread and the exception as arguments. If a thread has not had its UncaughtExceptionHandler explicitly set, then its ThreadGroup object acts as its UncaughtExceptionHandler. If the ThreadGroup object has no special requirements for dealing with the exception, it can forward the invocation to the default uncaught exception handler.
Java allows you to install a default exception handler for threads, for just this very reason. You have three options in doing so:
- You can set it for a specific Thread
- You can set it for a ThreadGroup (which means for all Threads in that group)
- You can set it VM wide for all Threads regardless
在Android中,我们一般会选用第三种方法。需要特别注意一点的是这个UncaughtExceptionHandler也是个链式的处理流程。之前发现线上ACRA统计的崩溃信息有点少,后来“偶然”了解到提到异常的抛出。后来看了下ACRA的代码,发现ACRA和Umeng也会将异常向外抛出,外层可以进一步处理。但是如果我们自定义的CrashHandler没有将异常抛给外层所以,ACRA就可能会丢数据了。(ACRA是肯定丢,因为ACRA在自定义的Handler的外层,但是没找到Umeng具体初始化Handler的时机,感觉Umeng初始化的晚一些,应该不会丢数据)
具体是这样的:
- 重写系统的ExceptionHandler之前,缓存住之前的Handler
defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(this);
- 对异常进行我们的自定义处理。处理完成之后将异常抛给上层Handler。并且这个回调是在主线程执行,所以我们不用手动调用 System.exit().
public void uncaughtException(Thread thread, Throwable ex) {
collectDeviceInfo();
saveCrashInfo2File(ex);
if (defaultHandler != null) {
defaultHandler.uncaughtException(thread, ex);
}
}
希望大家对此有所了解~