android timeout,Android中的TimeoutExceptions

有时会遇到以下崩溃:

The error is a variation of: "com.android.internal.BinderInternal$GcWatcher.finalize() timed out after 10 seconds"

java.util.concurrent.TimeoutException: android.os.BinderProxy.finalize() timed out after 10 seconds

at android.os.BinderProxy.destroy(Native Method)

at android.os.BinderProxy.finalize(Binder.java:459)

at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:187)

at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:170)

at java.lang.Thread.run(Thread.java:841)

它其实是发生在 GcWatcher.finalize, BinderProxy.finalize 和 PlainSocketImpl.finalize 中的一类TimeoutExceptions。这个异常90%都是发生在4.3、4.4的android系统上。

这个问题的根源在于设备会'Goes to Sleep'一会儿,就是说操作系统会通过熄屏、降低cpu循环等方式降低电量消耗,进入休眠状态。它是通过在内核层暂停进程的方式来实现的。这可能发生在常规app运行的过程中, 但是会停在一次内核调用上,比如内核层的上下文切换。这就是Dalvik GC参与最初所说TimeoutExceptions问题的方式。

Dalvik GC的基本工作方式就是,在GC循环中将收集到的一系列的对象去销毁,其主要流程可以描述为:

take starting_timestamp,

remove object for list of objects to release,

release object - finalize() and call native destroy() if required,

take end_timestamp,

calculate (end_timestamp - starting_timestamp) and compare against a hard coded timeout value of 10 seconds,

if timeout has reached - throw the concurrent.TimeoutException

and kill the process.

现在思考下接下来的这个场景:

有一个后台运行的进程,在运行过程中,对象被创建、使用以及被收集(以释放内存)。一般的,应用不会使用Wakelock,因为会很耗电并且也没必要,这意味着应用会不时的执行GC动作。通常情况下,GC动作会正常的执行完成而不会被挂起。但是,有些时候(很稀少),操作系统会在GC动作的过程中进入休眠。如果你的应用运行时间足够长,它就有可能发生。现在,想一下GC循环中的有关时间戳的逻辑:有可能发生,设备开始进行GC,并且在处理系统对象销毁(native层的destroy())的过程中进入休眠, 然后被唤醒,恢复运行,记录现在的时间戳,也就是说这次GC动作花费的时间=销毁动作执行时长+休眠时长。如果休眠时间超过10s, 就会抛出concurrent.timeout异常。

这个问题不能完全避免,只要你的应用在后台运行。我们可以通过调用wakelock减少设备休眠,但这个方法会引来一系列问题。最靠谱的方法还是,** 尽量减少GC动作的被调用次数 **,使得这个场景少出现。

另外,在Android5.0+系统上,因为使用了ART GC,使得这个崩溃的发生机率大大降低了。

目前Android project增加了大量的关于'GC是如何(在ART上)工作' 的之类的文档,感兴趣的话,可以看看:https://source.android.com/devices/tech/dalvik/gc-debug.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值