Android AssetManager finalize timed out 的坑

前言

最近遇到一个 Crashjava

java.util.concurrent.TimeoutException: android.content.res.AssetManager.finalize() timed out after 120 seconds
	at android.content.res.AssetManager.destroy(Native Method)
	at android.content.res.AssetManager.finalize(AssetManager.java:576)
	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)
复制代码

乍一看没有任何业务相关的代码,不过数量还挺多,并且大多数是 OPPO 手机。android

缘由

看 Crash 堆栈,猜想应该是资源回收超时了,不过具体缘由还不清楚。从搜索引擎了解到,这个问题主要缘由有如下缘由:bash

  1. 对象 finalize() 方法耗时较长
    当 finalize() 方法中有耗时操做时,可能会出现方法执行超时。耗时操做通常有两种状况,一是方法内部确实有比较耗时的操做,好比 IO 操做,线程休眠等。
  2. 5.0 版本如下机型 GC 过程当中 CPU 休眠致使
    有种观点认为系统可能会在执行 finalize() 方法时进入休眠, 而后被唤醒恢复运行后,会使用如今的时间戳和执行 finalize() 以前的时间戳计算耗时,若是休眠时间比较长,就会出现 TimeoutException。
  3. IO 负载太高
    许多类的 finalize() 都须要释放 IO 资源,当 APP 打开的文件数目过多,或者在多进程或多线程并发读取磁盘的状况下,随着并发数的增长,磁盘 IO 效率将大大降低,致使 finalize() 方法中的 IO 操做运行缓慢致使超时。
  4. FinalizerDaemon 中线程优先级太低
    FinalizerDaemon 中运行的线程是一个守护线程,该线程优先级通常为默认级别 (nice=0),其余高优先级线程得到了更多的 CPU 时间,在一些极端状况下高优先级线程抢占了大部分 CPU 时间,FinalizerDaemon 线程只能在 CPU 空闲时运行,这种状况也可能会致使超时状况的发生。(从 Android 8.0 版本开始,FinalizerDaemon 中守护线程优先级已经被提升,此类问题已经大幅减小)

解决方案

根本的解决方案是:优化代码,资源及时释放,从根源上避免资源回收超时。多线程

不过因为代码量的问题,短时间内没法尝试该方案,那么只有退而求其次,寻求缓解方案。并发

从网上看到关于该问题的解决方案主要有如下两个:ide

  1. 手动修改 finalize() 方法超时时间
  2. 手动停掉 FinalizerWatchdogDaemon 线程

直接说结论,这两种方法都是无效的,因此终极解决方案是优化

class ExceptionHandler : Thread.UncaughtExceptionHandler {
    private val defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()

    override fun uncaughtException(t: Thread?, e: Throwable?) {
        if (t?.name == "FinalizerWatchdogDaemon" && e is TimeoutException) {
            // ignore it
        } else {
            defaultExceptionHandler.uncaughtException(t, e)
        }
    }
}
复制代码

外部调用 Thread.setDefaultUncaughtExceptionHandler(ExceptionHandler()) 替换异常处理器。搜索引擎

既然没法解决,那么就直接忽略它,避免对用户形成影响。spa

更新

评论区有大牛提出了更完美的解决方案,你们能够尝试一下。感谢 @wfwf线程

参考

江义旺:滴滴出行安卓端 finalize time out 的解决方案

相关文章
相关标签/搜索