目录
为什么标题说是“缓解之策”,因为这没法根治,如果要根治的话,请优化代码!
一、背景
最近项目组反馈,谷歌后台收到好多崩溃,如图
从堆栈中看,根本看不出是哪里导致的崩溃,只知道是TImeoutException!
哎,头大,怎么解决呢?!这么多崩溃,肯定得解决啊!
二、解决方案
1、分析问题
初步分析,导致该崩溃的原因为,AssetManager在释放资源的时候,调用AssetInputStream#close方法时,出现了超时,但比较坑的是,从堆栈信息看,并不知道是哪段代码出问题,先确保SDK的代码没有问题,找到SDK中使用到AssetManager的地方,用完务必要进行close操作!但是,问题并没有解决。还是继续报错!
2、寻找业界的解决方案
找到一篇讲得比较详细的文章:滴滴出行安卓端 finalize time out 的解决方案
这篇文章讲的主要思路,就是如何去避开这个崩溃,自定义Thread.UncaughtExceptionHandler,当捕捉到这个崩溃的时候,直接忽略,不让APP崩溃!
该崩溃出现的过程:
- FinalizerDaemon 执行对象 finalize() 超时。
- FinalizerWatchdogDaemon 检测到超时后,构造异常交给 Thread的defaultUncaughtExceptionHandler 调用 uncaughtException() 方法处理。
- APP 停止运行。
Thread 类的 defaultUncaughtExceptionHandler 我们很熟悉了,Java Crash 捕获一般都是通过设置 Thread.setDefaultUncaughtExceptionHandler() 方法设置一个自定义的 UncaughtExceptionHandler ,处理异常后通过链式调用,最后交给系统默认的 UncaughtExceptionHandler 去处理,在 Android 中默认的 UncaughtExceptionHandler 逻辑如下:
public class RuntimeInit {
...
private static class UncaughtHandler implements Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread t, Throwable e) {
try {
...
// Bring up crash dialog, wait for it to be dismissed 展示APP停止运行对话框
ActivityManagerNative.getDefault().handleApplicationCrash(
mApplicationObject, new ApplicationErrorReport.CrashInfo(e));
} catch (Throwable t2) {
...
} finally {
// Try everything to make sure this process goes away.
Process.killProcess(Process.myPid()); //退出进程
System.exit(10);
}
}
}
private static final void commonInit() {
...
/* set default handler; this applies to all threads in the VM */
Thread.setDefaultUncaughtExceptionHandler