应用程序发生异常(面试官为什么应用出现异常会崩溃)

异常?崩溃?不是应该的吗?这.... 看到这个问题是不是这样 -> 1、为什么发生Exception后应用会发生奔溃? 当我们的应用发生未捕获异常后程序会回调到Thread 的dispatchUncaughtExcepti...

异常?崩溃?不是应该的吗?这....

看到这个问题是不是这样 ->

面试官:为什么应用出现异常会崩溃?

1、为什么发生Exception后应用会发生奔溃?

当我们的应用发生未捕获异常后程序会回调到Thread 的dispatchUncaughtException方法,如下:

//Thread.javapublic final void dispatchUncaughtException(Throwable e) { ...省略部分代码 // END Android-added: uncaughtExceptionPreHandler for use by platform. getUncaughtExceptionHandler().uncaughtException(this, e);}

然后通过getUncaughtExceptionHandler去获取UncaughtExceptionHandler对象

//Thread.javapublic UncaughtExceptionHandler getUncaughtExceptionHandler() { return uncaughtExceptionHandler != null ? uncaughtExceptionHandler : group;}

正常我们都没有设置UncaughtExceptionHandler,所有最后会将异常交给group(ThreadGroup)的uncaughtException进行处理,如下:

//ThreadGroup.javapublic 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.javapublic static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){ return defaultUncaughtExceptionHandler;}

那么Thread类的defaultUncaughtExceptionHandler是什么时候被赋值的呢?

是在RuntimeInit类的入口函数main函数中的commonInit方法:

//RuntimeInit.javapublic static final void main(String[] argv) { ... commonInit(); ...}//RuntimeInit.javaprotected static final void commonInit() { ... Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler)); ...}

这个给Thread的setDefaultUncaughtExceptionHandler设置了一个KillApplicationHandler的handler。KillApplicationHandler的uncaughtException方法如下:

//KillApplicationHandler.java@Overridepublic 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函数中进行处理。和上文中逻辑一样。

  • 发表于 2022-11-07 10:44
  • 阅读 ( 104 )
  • 分类:互联网

0 条评论

请先 登录 后评论
锄禾锐志
锄禾锐志

765 篇文章

你可能感兴趣的文章

相关问题