最近项目升大版本,targetSdkVersion 从 Android 6.0(version 21) 直接升到 Adnroid 9.0(version 28),跨度有点大,但是没有像升到 Android 6.0 那样工作量大。升完之后,在小米5、小米4C 2款测试机上 App 启动直接无响应了,在我的小米 MIX 上没问题。于是测试机调试之旅开始了。。。
在 SplashActivity onCreate 的方法里打断点进都进不去,有点懵,所以将目标定位到 Application 初始化了。看着 Application 相关初始化的代码,没发现什么大问题。打断点逐步调试,运行到某一行时直接就无响应了,后面的代码也不执行了,logcat 也看不到有用的信息,有点摸不着头脑。后面 Google 发现可以直接看到手机 ANR 的日志,路径为:/data/anr/traces.txt,于是很欢快的将日志导出到电脑:
1 | adb pull /data/anr/traces.txt d:/test |
然后看到 traces.txt:
1 | ----- pid 1928 at 2019-07-03 17:42:50 ----- |
日志很多,Cmd line 就是当前 ANR 应用的包名,通过日志,可以得到一些有效信息:
1 | main:main标识是主线程,如果是线程,那么命名成“Thread-X”的格式,x 表示线程 id,逐步递增 |
找到 “main”,可以看到,在 Application 的 onTrimMemory 时调用了 Glide 的 get 方法,后面一系列操作导致的主线程变成 Waiting 状态了。
1 |
|
最终会调用到 GlideAppModule 的 registerComponents 方法:
1 | @Override |
然后看到 GlideProgressManager:
1 | static OkHttpClient getOkHttpClient() { |
XXXHttpClient:
1 | private static volatile OkHttpClient defaultHttpClient; |
很标准的 Double-Check 单例模式,感觉没啥大问题,但是为啥会导致 ANR 呢?
因为升大版本,将绝大多数注意力都放到升级注意项了,比如 FileProvider 等等,但是正好基础库在大版本升级时,将 OkHttp 从 2.x 升到 3.x,上面的代码正时此时添加进来的,所以没升大版本一切正常。解决问题的话,将 Application 中 Glide 相关操作直接干掉就好了,Glide 内部有自己的内存控制策略,无需开发者关心了吧。
写这篇文章主要是记录一下可以通过拉取 traces.text 日志来分析 ANR,但是为什么这样的代码导致了 ANR 还没研究透,待我研究好了再来更新此文。