Thread starting during runtime shutdown问题的解决

安卓5.0及以后的系统 在 UncaughtExceptionHandler 方法中 开启线程 有可能会 使线程中的  Runnable 不执行,原因据说uncaughtException方法执行完成后ART环境就shutdown了


真正原因如下:

调用网络发送部分的策略是启动一个新的Service组件,读取持久化存储的数据,然后发送到服务端。至于为什么不直接开一个新的thread调用这个发送操作是有原因的。

  • Android 4.4.4 默认的http client库是基于okhttp的,在获取HTTP返回信息的时候为了防止阻塞会开新的thread。
  • Android 6.0使用了ART替代Dalvik开始,在shutdown的过程中不能开新的thread,否则又会跑出异常java.lang.InternalError: Thread starting during runtime shutdown
因此ACRA的解决办法就是开新的process的Service调用http,这个解决方案的讨论过程见:

那么bugly 在5.0之后的系统也能正常使用,可能也是开启了新的上报进程来处理的。所以网上流传的那一套安卓UncaughtExceptionHandler 机制已经不再适用了。fuck


可参考:https://my.oschina.net/azard/blog/614843


什么是 ACRA? 请移步这里, 应该是一个 国外版的专注于Android APP的 bugly系统

https://github.com/ACRA/acra


===================================================================================================

问题描述与分析:

  为了获取Crash日志,项目中实现了UncaughtExceptionHandler接口对未知异常进行捕获并上传到服务器中,同时停止App运行。在Android5.0以下系统一直未出现过问题,但是突然发现在Android 5.0以上的机器中这段代码出现了java.lang.InternalError: Thread starting during runtime shutdown(更多异常信息见最后部分的附录),在stackoverflow中得到了一些帮助:这个问题是因为线程开启的太晚了!

  什么时候开启线程才算得上“太晚了”呢? 在我的项目中UncaughtExceptionHandler实现类捕获到异常时(也就是UncaughtExceptionHandler接口的uncaughtException方法执行时),开启了一个线程用于上传崩溃日志,而在线程中上传崩溃日志时创建了HttpClient发送网络请求。HttpClient创建时设置了ThreadSafeClientConnManager来管理连接,而在ThreadSafeClientConnManager的源码中又一次开启了线程!也就是说,uncaughtException方法执行时在开启的线程中又开启了新的线程,这样可能会导致uncaughtException方法在执行完成时,“线程中的线程”才start(),而据说uncaughtException方法执行完成后ART环境就shutdown了(uncaughtException方法结束时ART是否会真的shutdown,这一点有待考证,笔者也仅是从其他非官方资料中得知),这种情况下就会抛出java.lang.InternalError: Thread starting during runtime shutdown。

  为了验证这个问题,编写了一段简单的代码:实现UncaughtExceptionHandler的uncaughtException方法,在uncaughtException方法中开启一个线程,在这个线程中再开一线程,同时在MainActivity中故意制造一个异常发生,此时果然会出现java.lang.InternalError: Thread starting during runtime shutdown(并不是每次都出现,因为如果uncaughtException方法执行结束之前,两个线程都完成start(),此问题就不会出现)。

 

解决方法:

  避免在uncaughtException方法中出现线程嵌套:针对我的项目,不再去在线程中创建HttpClient(因为HttpClient创建时还会开启线程,这就造成了线程中再次开启线程),而是先创建HttpClient对象,再在线程中使用HttpClient对象。这样就可以确保uncaughtException方法结束之前HttpClient已经被创建,HttpClient中开启线程也就不会有问题。

 

附异常信息:

java.lang.InternalError: Thread starting during runtime shutdown at java.lang.Thread.nativeCreate(Native Method) at java.lang.Thread.start(Thread.java:1042) at org.apache.http.impl.conn.tsccm.AbstractConnPool.enableConnectionGC(AbstractConnPool.java:140) at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager.createConnectionPool(ThreadSafeClientConnManager.java:120) at org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager.<init>(ThreadSafeClientConnManager.java:98) at

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值