如果我们需要监控Android App中发生的Crash异常,只需要做下面动作
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
xxxx
}
}
实现方法即可,然后在该方法实现异常的记录、上报工作即可。
我们打印下堆栈,看下哪里调用到uncaughtException的
04-13 09:36:23.549 12456 12708 E yxlog : com.xxx.base.application.InitApplication$1.uncaughtException(InitApplication.java:80)
04-13 09:36:23.549 12456 12708 E yxlog : com.baidu.mobstat.ak.uncaughtException(SourceFile:34)
04-13 09:36:23.549 12456 12708 E yxlog : com.umeng.analytics.pro.l.uncaughtException(CrashHandler.java:37)
04-13 09:36:23.549 12456 12708 E yxlog : cn.p.jiguang.cf.a.uncaughtException(Unknown Source:39)
04-13 09:36:23.549 12456 12708 E yxlog : java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1068)
04-13 09:36:23.549 12456 12708 E yxlog : java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1063)
04-13 09:36:23.549 12456 12708 E yxlog : java.lang.Thread.dispatchUncaughtException(Thread.java:1955)
从上面可以看到,最终是由Thread.dispatchUncaughtException。那么又是谁调用了这个方法呢?
答案是虚拟机调用的。我们搜索一下Android的源码
最后发现调用位置是在art/runtime/thread.cc中看到调用位置
void Thread::HandleUncaughtExceptions(ScopedObjectAccessAlreadyRunnable& soa) {
if (!IsExceptionPending()) {
return;
}
ScopedLocalRef<jobject> peer(tlsPtr_.jni_env, soa.AddLocalReference<jobject>(tlsPtr_.opeer));
ScopedThreadStateChange tsc(this, kNative);
// Get and clear the exception.
ScopedLocalRef<jthrowable> exception(tlsPtr_.jni_env, tlsPtr_.jni_env->ExceptionOccurred());
tlsPtr_.jni_env->ExceptionClear();
// Call the Thread instance's dispatchUncaughtException(Throwable)
//由这里调用的
tlsPtr_.jni_env->CallVoidMethod(peer.get(),
WellKnownClasses::java_lang_Thread_dispatchUncaughtException,
exception.get());
// If the dispatchUncaughtException threw, clear that exception too.
tlsPtr_.jni_env->ExceptionClear();
}
我们就不深入虚拟机继续看了。