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 的解決方案

相關文章
相關標籤/搜索