共计 4223 个字符,预计需要花费 11 分钟才能阅读完成。
前言
相比于产生应用程序解体,产生 ANR 更加让人头大,次要起因是解体产生的时候会在 Logcat 中打印出产生异样的地位,开发人员很容易就能定位到解体并解决,显然 ANR 没那么轻松;然而咱们大可不必这么难过,因为有问题就会有解决办法,解决不了,只是因为没有用对办法
总体思路
- 导出 ANR 日志信息,依据日志信息,判断确认产生 ANR 的包名类名,过程号,产生工夫,导致 ANR 起因类型等。
- 关注系统资源信息,包含 ANR 产生前后的 CPU,内存,IO 等系统资源的应用状况。
- 查看主线程状态,关注主线程是否存在耗时、死锁、等锁等问题,判断该 ANR 是 App 导致还是零碎导致的。
- 联合利用日志,代码或源码等,剖析 ANR 问题产生前,利用是否有异样,其中具体问题具体分析。
导出 ANR 日志
ANR 问题产生时,零碎会收集 ANR 相干的日志信息,CPU 应用状况,trace 日志也就是各线程执行状况等信息,生成一个 traces.txt 的文件并且放在 /data/anr/ 门路下。
留神:每一次新的 ANR 问题的产生,会把之前的 ANR 信息笼罩掉。
咱们能够通过 adb 命令将 traces 文件导出到本地。
adb root
adb shell ls /data/anr
adb pull /data/anr/<filename>
读取要害日志信息
1)在 log 中找到 ANR 产生信息:Traces 文件中的关键字,例如:
09-24 15:20:20.211 1001 1543 1570 XXXXXXX:ANR in xxxxxx
09-24 15:20:20.211 1001 1543 1570 XXXXXXX:PID: xxxxx
09-24 15:20:20.211 1001 1543 1570 XXXXXXX:Reason: xxxxxx
其中:
- ANR in 中,包含导致 ANR 的包名,类名
- PID 中,为产生 ANR 的过程 PID
- Reason 中,为导致 ANR 的起因,例如 keyDispatchingTimedOut
2)找到 CPU Usage 信息
09-24 15:20:20.211 1001 1543 1570 XXXXXX:CPUusage from xxx to xxx ago xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
09-24 15:20:20.211 1001 1543 1570 XXXXXX:CPUusage from xxx to xxx later xxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxx
其中
- ago 示意 ANR 产生前的 CPU 的应用状况
- later 示意 ANR 产生后的 CPU 的应用状况
- 重点关注 xxx%TOTAL: xxx% user + xxx% kernel + xxx% iowait,可通过这几项理解到 CPU 的占用状况。
具体分析
剖析 CPU usage 当前,如若还是无奈找出问题起因,则须要进一步剖析 trace 文件。traces 文件中具体记录了产生 ANR 前后该过程的各个线程的 Stack,个别从主线程的 stack 动手剖析,查看剖析 ANR 问题产生前,利用是否有异样。
其中不同场景下的 ANR 问题状况不大雷同,须要具体情况具体分析,此处就不开展详细描述。
ANR 问题难点及破题思路
ANR 难点
用户在利用内的绝大部分操作,比方按钮点击,加载资源,页面跳转等操作,都须要有 App 的被动反馈,但 ANR 产生时,在用户期待数秒后,仅会弹出一个“利用无响应”的弹窗给用户,这会给用户带来“利用难用”的感觉,极其影响用户体验。
然而,现网中的 ANR 问题又很难解决,问题包含但不限于:
- 平时的测试难以笼罩,毕竟 ANR 经常出现在老设施、弱网络环境的场景下,测试难以做到全场景笼罩。
- 对于现网利用的 ANR 问题,如果问题非必现,则定位难度较高,须要有能够复现问题的理论设施在身边,能力获取到具体日志 trace 等信息。
- ANR 问题定位简单,影响因素多,一些新负责定位 ANR 问题的同学,上手艰难,问题解决比拟依赖教训。
ANR 解决新计划
除了依赖现有传统的 ANR 问题定位教训,配合第三方利用监控平台、进行 ANR 问题的解决,也是方便快捷的 ANR 解决伎俩。
晋升用户体验火烧眉毛,但 ANR 问题对用户体验影响大,定位解决 ANR 问题老大难,针对这个需要痛点,越来愈多的第三方开始钻研并对外提供利用性能监控工具。
性能治理(App Performance Management,简称 APM)是华为 AppGallery Connect 品质系列服务中的其中一项,提供分钟级利用性能监控能力,其 ANR 剖析性能,更是解决 ANR 问题定位与解决的最佳搭档。应用 AGC 性能治理服务监控利用 ANR,可能为您带来以下益处:
1. 实时监控现网利用 ANR,现网利用 ANR 趋势全把握。
2.ANR 现场信息主动采集和展现,大部分状况无需复现,在线定位问题。
3. 通过 APM 页面,定位思路系统化,疾速上手 ANR 问题定位,及时解决问题。
ANR 问题解决案例整顿
接下来以华为 AGC 性能治理服务为例,介绍配合 AGC 性能治理服务,如何疾速定位典型的 ANR 问题。
案例(一):死锁导致的 ANR 问题定位
发现问题
在华为 AGC 控制台的我的我的项目 - 品质 - 性能治理页面,在“ANR 剖析”页签下,发现排在第一位的“用户 ANR 率”高达 16.67%,决定优先解决该类 ANR 问题。
定位问题
点开 TOP 排行榜中该类问题卡片,进入了该类“ANR 问题详情”页面,进一步查看剖析该 ANR 问题的数据报告。
在这个“ANR 问题详情 ”页面中,剖析用户数散布饼图,发现该类 ANR 问题在“ 利用版本 2.0”、“手机型号 HUAWEI VOG-AL10”、“零碎版本 10”这三个条件下,ANR 影响的用户数最多。
在报告下方的“产生记录”中,找到满足这三个条件的产生记录,点击“查看详情”筹备针对具体的问题进行剖析。
(1) 剖析系统资源状态 首先,通过报告,发现该问题产生时,CPU 占用是 20%、IO 占用是 0%、未产生过低内存、利用被调配堆是 26.50MB、利用已用堆是 8.69MB,线程数是 61,从系统资源来看,未呈现显著的异样,如下图所示:
因为 ANR 问题起因能够分为两大类,一是系统资源有余导致,二是本身代码逻辑导致,综合以上系统资源信息,该 ANR 问题不是因为系统资源有余导致,那么剖析该 ANR 问题思路转变为:该 ANR 问题由本身代码逻辑导致,接下来,咱们顺着该思路剖析这次的 ANR 问题。
(2) 查看主线程状态:发现 ANR 代码片段 本身代码
逻辑导致 ANR 问题,其次要剖析思路是查看主线程堆栈及线程状态,咱们在性能治理页面上“主线程堆栈”页签中可能找到问题堆栈,发现该问题产生时,主线程处于获取锁状态,到此咱们可能得出结论:该 ANR 问题是因为主线程始终在期待锁资源,而被阻塞,导致了后续输出事件未被响应,从而触发了利用的“Input dispatching timed out”类型的 ANR。
查看具体的堆栈信息,咱们找到了 ANR 问题代码片段,发现死锁是产生在“com.aiops.hiperformance.MainActivity.dispatchActivityDestroyed”调用中。查看代码发现,死锁产生在“mLock.readLock().lock()”函数中。
通过在代码中搜寻 mLock 加锁代码的调用,发现了仅在 MainActivity 文件中,才会存在“mLock.readLock.lock()”代码,由此判断,异样代码仅存在于 MainActivity 中,因而咱们放大了问题代码范畴。在正在的代码编写过程中,锁的申请与开释曾经成为一种编码习惯,如果锁未开释,可能是在开释锁之前,呈现了某种咱们编码未思考的异样,导致锁未开释或开释失败。由此剖析,咱们接下来尝试应用“找到 ANR 问题产生之前,利用是否有异样产生”的思路,持续剖析。
咱们先找到申请锁动作开始工夫点,由阻塞动作开始工夫点往前剖析,寻找异样信息。咱们切换到“ANR 信息”页签,发现主执行队列首元素在 5.5s 前曾经存在,ANR 产生工夫是“2020-09-27 09:48:27”, 因而咱们可计算出获取锁动作大略是在“2020-09-27 09:48:21”产生。
(3) 查看利用日志 接下来,咱们把页签切到“系统日志”中,咱们目前晓得锁获取动作在“2020-09-27 09:48:21”左右产生。咱们接下来仅须要在日志中,从该工夫点往前剖析,看是否由相干异样,是导致该锁未被开释的关键因素。
咱们发现在“09:48:18.365”时零碎抛出了“OutofBoundsException”异样,并且打印了异样堆栈,咱们发现,该异样就呈现在 MainActivity,也就是咱们之前的问题代码范畴中,咱们通过该堆栈,找到了异样代码。
发现在“getShareDataInterceptor”调用时,抛出了“越界异样”,导致了“mLock.readLock”未被开释,由此咱们曾经晓得导致该 ANR 问题的具体起因:异样场景导致锁资源未被开释,从而造成了主线程呈现死锁。
解决问题
为了修复了该问题,咱们做了以下措施,解决该问题的同时,预防同类问题产生:
- 剖析异样具体起因并批改代码,避免越界异样再次出现。
- 捕捉该异样,爱护代码在资源开释前被异样抛出。
- 排查其余代码,在资源开释前,加上爱护,保障资源及时开释。
文末
对于很多初中级 Android 工程师而言,想要晋升技能,往往是本人摸索成长,不成体系的学习效果低效漫长且无助。整顿的这些架构技术心愿对 Android 开发的敌人们有所参考以及少走弯路,本文的重点是你有没有播种与成长,其余的都不重要,心愿读者们能谨记这一点。
最初想要拿高薪实现技术晋升薪水失去质的飞跃。最快捷的形式,就是有人能够带着你一起剖析,这样学习起来最为高效,所以为了大家可能顺利进阶中高级、架构师,我顺便为大家筹备了一套高手学习的源码和框架视频等精品 Android 架构师教程,保障你学了当前保障薪资回升一个台阶。当你有了学习线路,学习哪些内容,也晓得当前的路怎么走了,实践看多了总要实际的。
进阶学习视频
附上:收集的二十套一二线互联网公司 Android 面试真题?(含 BAT、小米、华为、美团、滴滴)和我本人整顿 Android 温习笔记(蕴含 Android 根底知识点、Android 扩大知识点、Android 源码解析、设计模式汇总、Gradle 知识点、常见算法题汇总。)
明天的文章就到这里,感谢您的浏览,有问题能够在评论区留言探讨,期待与大家共同进步。喜爱的话不要忘了 三连。大家的反对和认可,是我分享的最大能源。