Android踩坑經驗-Finalize TimeoutException原因及解決方案

調用棧信息:
在這裏插入圖片描述
背景知識:FinalizerDamemon和FinalizerWatchdogDaemon
FinalizerDamemon
析構守護線程,重寫了finalize的對象,在創建時會新建一個FinalizerReference,這個對象是強引用類型,封裝了override finalize()的對象,下面直接叫原對象。原對象沒有被其他對象引用時(FinalizeReference除外),執行GC不會馬上被清除掉,而是放入一個靜態鏈表中(ReferenceQueue),析構守護線程獲得時間片後,彈出鏈表對象,並執行原對象finalize()方法,對應的FinalizerReference對象在下次執行GC時就會被清理掉。
FinalizerWatchdogDaemon
當一個實例的finalize函數,花費超過MAX_FINALIZATION_MILLIS(默認10s,很多第三方廠商改爲60s),則FinalizerWatchdogDaemon線程會讓VM退出,應用程序程序crash
原因:
1:Finalize對象累積太多,導致FinalizerDaemon線程來不及處理
Q:項目中沒有類重寫finalize方法,什麼對象累積太多?
可能項目中沒有類重寫finalize方法,但Android系統中有非常多的類實現了finalize方法,如:Binder,View,Matrix,Bitmap,AssetManager等
2:運行過程中息屏,或者某些省電模式下,系統CPU降頻,FinalizerDaemon線程獲得時間片短且執行速度慢導致超時
3:某個析構函數調用阻塞
解決方法:
這個問題,並不像NPE那樣,可以快速定位解決,甚至來說,這個問題幾乎無解。但可以通過反射調用讓FinalizerWatchdogDaemon停止工作,從而讓這種crash消除掉。
(現在Android版本不斷升級,P以上對反射使用有限制,因此無法通過反射停止FinalizerWatchdogDaemon線程,但Android P的機器目前都是高端機,性能較好的機器出現此問題的概率本身就比較小,因此基本能解決finalize timeout問題)
參考代碼:
在這裏插入圖片描述
還有一些理論上可能有幫助的措施:
1:減少內存佔用,避免不必要的對象創建
2:消除內存泄露問題,緩解GC壓力

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章