转:
背景
当发生Crash时,手机信息,上报异常信息至服务器。
出现了Crash:
AndroidRuntime: FATAL EXCEPTION: Crashlytics Exception Handler1
java.lang.InternalError: Thread starting during runtime shutdown
E AndroidRuntime: java.lang.InternalError: Thread starting during runtime shutdown
E AndroidRuntime: at java.lang.Thread.nativeCreate(Native Method)
这个问题是因为线程开启的太晚了!
分析
什么时候开启线程才算得上“太晚了”呢? 在我的项目中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中开启线程也就不会有问题。