finalize time out 的解决方案

背景

最近项目上了一个新版本,在TalkingData错误上报发现错误率最高到0.50%,之前版本错误率一直在0.20%~0.25%,新版本错误率直接飙升一倍以上。查看错误上报日志,发现有个异常绝对的突出,拉高了错误率。

几种错误日志如下:
1、超时120秒

java.util.concurrent.TimeoutException: com.android.org.conscrypt.OpenSSLDigestContext.finalize() timed out after 120 seconds
    at com.android.org.conscrypt.NativeCrypto.EVP_MD_CTX_destroy(Native Method)
    at com.android.org.conscrypt.OpenSSLDigestContext.finalize(OpenSSLDigestContext.java:27)
    at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:217)
    at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:200)
    at java.lang.Thread.run(Thread.java:818)

2、超时10秒

java.util.concurrent.TimeoutException: com.android.org.conscrypt.OpenSSLDigestContext.finalize() timed out after 10 seconds
    at com.android.org.conscrypt.NativeCrypto.EVP_MD_CTX_destroy(Native Method)
    at com.android.org.conscrypt.OpenSSLDigestContext.finalize(OpenSSLDigestContext.java:27)
    at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:198)
    at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:177)
    at java.lang.Thread.run(Thread.java:818)

3、超时30秒

java.util.concurrent.TimeoutException: com.android.org.conscrypt.NativeRef$EVP_MD_CTX.finalize() timed out after 30 seconds
    at com.android.org.conscrypt.NativeCrypto.EVP_MD_CTX_destroy(Native Method)
    at com.android.org.conscrypt.NativeRef$EVP_MD_CTX.finalize(NativeRef.java:116)
    at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:202)
    at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:185)
    at java.lang.Thread.run(Thread.java:833)

4、超时40秒

java.util.concurrent.TimeoutException: com.android.org.conscrypt.OpenSSLDigestContext.finalize() timed out after 40 seconds
    at com.android.org.conscrypt.NativeCrypto.EVP_MD_CTX_destroy(Native Method)
    at com.android.org.conscrypt.OpenSSLDigestContext.finalize(OpenSSLDigestContext.java:27)
    at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:194)
    at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:177)
    at java.lang.Thread.run(Thread.java:818)

5、超时15秒

java.util.concurrent.TimeoutException: com.android.org.conscrypt.OpenSSLDigestContext.finalize() timed out after 15 seconds
    at com.android.org.conscrypt.NativeCrypto.EVP_MD_CTX_destroy(Native Method)
    at com.android.org.conscrypt.OpenSSLDigestContext.finalize(OpenSSLDigestContext.java:27)
    at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:192)
    at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:175)
    at java.lang.Thread.run(Thread.java:818)

之所以有 10s、15s,30s,40s,120s等,是因为国内厂商修改了Daemons 类中 的 MAX_FINALIZE_NANOS值。

如何解决

网上查找了资料,发现原来滴滴出行也遇到此问题,而且他们有了较好的方案来缓解止损。
滴滴出行安卓端 finalize time out 的解决方案

解决方法

Java Crash 捕获一般都是通过设置 Thread.setDefaultUncaughtExceptionHandler() 方法设置一个自定义的 UncaughtExceptionHandler ,处理异常后通过链式调用,最后交给系统默认的 UncaughtExceptionHandler 去处理。从系统默认的 UncaughtExceptionHandler 中可以看出,APP Crash 时弹出的停止运行对话框以及退出进程操作都是在这里处理中处理的,那么只要不让这个代码继续执行就可以阻止 APP 停止运行了。
基于这个思路可以用如下代码缓解止损:

final Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                if (t.getName().equals("FinalizerWatchdogDaemon") && e instanceof TimeoutException) {
                    //ignore it
                } else {
                    defaultUncaughtExceptionHandler.uncaughtException(t, e);
                }
            }
        });

你可能感兴趣的:(finalize time out 的解决方案)