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压力

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