面试官:为什么应用出现异常会崩溃?
Posted 初一十五啊
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面试官:为什么应用出现异常会崩溃?相关的知识,希望对你有一定的参考价值。
异常?崩溃?不是应该的吗?这…
看到这个问题是不是这样 ->
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
@Override
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开发之旅
以上是关于面试官:为什么应用出现异常会崩溃?的主要内容,如果未能解决你的问题,请参考以下文章