此问题在oppo R9 系列的手机出现较多,而且主要集中在Android 5.1-6.0的手机系统。
TimeoutException,在Android 系统里会出现下面这些,在释放资源时,因耗时导致的,可能不是10s,可能会是20s,30s,60s,120s。具体跟手机有关。
android.database.CursorWindow.finalize() timed out after 10 seconds
java.util.regex.Matcher.finalize() timed out after 10 seconds
android.graphics.Bitmap$BitmapFinalizer.finalize() timed out after 10 seconds
org.apache.http.impl.conn.SingleClientConnManager.finalize() timed out after 10 seconds
java.util.concurrent.ThreadPoolExecutor.finalize() timed out after 10 seconds
android.os.BinderProxy.finalize() timed out after 10 seconds
android.graphics.Path.finalize() timed out after 10 seconds
这些都 会导致此闪退出现。这个bug,在stackoverflow数量还是比较 多的。
经过google查询,最终在
具体的分析及解决可以详细阅读滴滴移动团队 分享的文章
https://mp.weixin.qq.com/s/uFcFYO2GtWWiblotem2bGg
我按滴滴的文章,还是会闪退,对于 app的异常监听,可参考之前的一篇文章 https://www.jianshu.com/p/2cb297395bd4 。
由于我们App还集成了一些第三方 的SDK,这个SDK 里都有实现对 异常 的拦截处理,如jpush、umeng、神策打点。所以当我在自己的
Thread.UncaughtExceptionHandler,处理完后,会再抛出一个java.lang.RuntimeException,最终还是会走异常的处理逻辑,造成App闪退。
1 xxxxx.CrashHandler.uncaughtException()
2 com.umeng.analytics.pro.j.uncaughtException()
3 com.qiyukf.unicorn.j.d$1.uncaughtException()
4 cn.jiguang.a.a.c.e.uncaughtException()
5 com.tencent.bugly.crashreport.crash.e.b()
6 com.tencent.bugly.crashreport.crash.e.uncaughtException()
7 java.lang.Daemons$FinalizerWatchdogDaemon.finalizerTimedOut(Daemons.java:316)
8 java.lang.Daemons$FinalizerWatchdogDaemon.run(Daemons.java:238)
9 java.lang.Thread.run(Thread.java:833)
2019-07-23 11:24:31.277 11406-11419/xxxx E/[ FinalizerWatchdogDaemon:CrashHandler:uncaughtException():62 ]: ==thread==FinalizerWatchdogDaemon
2019-07-23 11:24:31.278 11406-11419/xxxx E/[ FinalizerWatchdogDaemon:CrashHandler:uncaughtException():67 ]: ===ex=java.util.concurrent.TimeoutException: xxxx.ui.index.FinlaizeTimeoutObject.finalize() timed out after 60 seconds
2019-07-23 11:24:31.278 11406-11419/xxxx E/[ FinalizerWatchdogDaemon:CrashHandler:uncaughtException():70 ]: ===ignore=
2019-07-23 11:24:31.280 11406-11419/xxxx E/AndroidRuntime: FATAL EXCEPTION: FinalizerWatchdogDaemon
Process: xxxx, PID: 11406
java.lang.RuntimeException: java.util.concurrent.TimeoutException: xxxx.ui.index.FinlaizeTimeoutObject.finalize() timed out after 60 seconds
at cn.jiguang.a.a.c.e.uncaughtException(Unknown Source:69)
at com.xiaomi.mipush.sdk.z.uncaughtException(Unknown Source:25)
at com.loc.ai.uncaughtException(Unknown Source:21)
at com.loc.ay.uncaughtException(Unknown Source:232)
at java.lang.Daemons$FinalizerWatchdogDaemon.finalizerTimedOut(Daemons.java:424)
at java.lang.Daemons$FinalizerWatchdogDaemon.runInternal(Daemons.java:285)
at java.lang.Daemons$Daemon.run(Daemons.java:105)
at java.lang.Thread.run(Thread.java:764)
Caused by: java.util.concurrent.TimeoutException: xxxx.ui.index.FinlaizeTimeoutObject.finalize() timed out after 60 seconds
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:373)
at java.lang.Thread.sleep(Thread.java:314)
at xxxx.ui.index.FinlaizeTimeoutObject.finalize(FinlaizeTimeoutObject.java:11)
at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:252)
at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:239)
at java.lang.Daemons$Daemon.run(Daemons.java:105)
at java.lang.Thread.run(Thread.java:764)
2019-07-23 11:24:34.356 11406-11419/xxxx E/[ FinalizerWatchdogDaemon:CrashHandler:uncaughtException():62 ]: ==thread==FinalizerWatchdogDaemon
2019-07-23 11:24:34.356 11406-11419/xxxx E/[ FinalizerWatchdogDaemon:CrashHandler:uncaughtException():67 ]: ===ex=java.lang.RuntimeException: java.util.concurrent.TimeoutException: xxxx.ui.index.FinlaizeTimeoutObject.finalize() timed out after 60 seconds
2019-07-23 11:24:34.356 11406-11419/xxxx E/[ FinalizerWatchdogDaemon:CrashHandler:uncaughtException():72 ]: ===ex=java.lang.RuntimeException: java.util.concurrent.TimeoutException: xxxx.ui.index.FinlaizeTimeoutObject.finalize() timed out after 60 seconds
2019-07-23 11:24:34.358 11406-11419/xxxx E/CrashReport: CrashReport has not been initialed! pls to call method 'initCrashReport' first!
2019-07-23 11:24:37.359 11406-11419/xxxx E/Tinker.TinkerUncaughtExceptionHandler: uncaughtException:java.util.concurrent.TimeoutException: xxxx.ui.index.FinlaizeTimeoutObject.finalize() timed out after 60 seconds
2019-07-23 11:24:37.359 11406-11419/xxxx W/Tinker.TinkerUncaughtExceptionHandler: tinker is not loaded
2019-07-23 11:24:37.361 11406-11419/xxxx E/Tinker.UncaughtHandler: TinkerUncaughtHandler catch exception:java.lang.RuntimeException: java.util.concurrent.TimeoutException: xxxx.ui.index.FinlaizeTimeoutObject.finalize() timed out after 60 seconds
at cn.jiguang.a.a.c.e.uncaughtException(Unknown Source:69)
at com.xiaomi.mipush.sdk.z.uncaughtException(Unknown Source:25)
at com.loc.ai.uncaughtException(Unknown Source:21)
at com.loc.ay.uncaughtException(Unknown Source:232)
at java.lang.Daemons$FinalizerWatchdogDaemon.finalizerTimedOut(Daemons.java:424)
at java.lang.Daemons$FinalizerWatchdogDaemon.runInternal(Daemons.java:285)
at java.lang.Daemons$Daemon.run(Daemons.java:105)
at java.lang.Thread.run(Thread.java:764)
Caused by: java.util.concurrent.TimeoutException: xxxx.ui.index.FinlaizeTimeoutObject.finalize() timed out after 60 seconds
at java.lang.Thread.sleep(Native Method)
at java.lang.Thread.sleep(Thread.java:373)
at java.lang.Thread.sleep(Thread.java:314)
at xxxx.ui.index.FinlaizeTimeoutObject.finalize(FinlaizeTimeoutObject.java:11)
at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:252)
at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:239)
at java.lang.Daemons$Daemon.run(Daemons.java:105)
at java.lang.Thread.run(Thread.java:764)
如何设计出一个TimeoutException。
先自己随便写一下类,暂且叫,CustomTimeoutException吧。重写finalize()方法,在里面将线程sleep 100s,这个是测试出来的,上文有提到,不同的手机 、系统对应超时时间不一样,我用了一个魅族 5.1的手机 ,20s,在小米 note 2 8.0 系统 是60s.
public class CustomTimeoutException {
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("====开始Timeout处理====");
// 每个手机触发 Timeout 的时长不同,看情况修改
Thread.sleep(100*1000);
System.out.println("====结束Timeout处理====");
}
}
然后在一个页面加一个点击事件,throwsTimeout()
private void throwsTimeout(){
new Thread(()->{
new CustomTimeoutException();
Runtime.getRuntime().gc();
System.runFinalization();
}).start();
}
点击按钮后,我们会看到打印 :
但迟迟不见: 日志.
注意,我在测试时,并不是每次出现,有时会打印“====结束Timeout处理====” 日志,猜测可能跟我 开启一下线程处理这个有关,因为我并没有阻塞 UI线程,App还是可以 继续使用。
为什么要开启一个线程,不然很容易造成ANR(10s),无法复现此问题。
经过这个,我最终并没有完全按滴滴提供的方法处理此异常。只要检测到是线程名是 FinalizerWatchdogDaemon,我就忽略此异常,这样,这样也就不会被其它的 异常处理 类强制 退出App。
/**
* 当UncaughtException发生时会转入该函数来处理
*/
@Override
public void uncaughtException(Thread thread, Throwable ex) {
System.out.println("==thread=="+thread.getName());
System.out.println("===ex="+ex);
System.out.println("===isTimeOut="+(ex instanceof TimeoutException));
System.out.println("=isThread=="+
TextUtils.equals(thread.getName(),
"FinalizerWatchdogDaemon"));
if(TextUtils.equals(thread.getName(),
"FinalizerWatchdogDaemon")) {
//&&ex instanceof TimeoutException)
System.out.println("===ignore=");
}else {
// 正常处理异常,该上抛的上抛,该交给系统 处理的交给系统处理。
}
虽然问题是解决了,但这并没有从根本上解决这个问题,真的要减少此异常的话,还是得规范开发的,尽量让App减少 GC的回收。
网友评论