1、ANR介绍
1.1 ANR是什么
ANR,全称为Application Not Responding,也就是应用程序无响应。如果 Android 利用的界面线程处于阻塞状态的工夫过长,就会触发“利用无响应”(ANR) 的谬误。
此时零碎会向用户显示一个对话框,ANR 对话框会为用户提供强行退出利用的选项。
1.2 ANR的四种类型
在Android零碎中,应用程序的响应由Activity Manager及Window Manager两个零碎服务所监控。通常状况下,利用呈现如下四类状况时,零碎将报ANR:
- KeyDispatchTimeout(最常见类型)—— input事件5s内未解决实现导致ANR产生,次要为按键和触摸事件;
日志关键字:InputDispatching Timeout
- BroadcastTimeout:—— BroadcastReceiver在特定工夫内未解决实现导致ANR产生(限度:前台播送10s;后盾播送60s);
日志关键字:Timeout of broadcast BroadcastRecord
- ServiceTimeout —— Service在特定的工夫内未解决实现导致ANR产生。(限度:前台服务20s;后盾服务200s);
日志关键字:Timeout executing service
- ContentProviderTimeout —— 内容提供者,在10s内未解决实现导致ANR产生;
日志关键字:Timeout publishing content providers
1.3 ANR的产生起因
通过大量ANR案例的剖析,总结出以下三个ANR问题产生的典型场景:
- 主线程被其余线程锁(占比57%):调用了thread的sleep()、wait()等办法,导致的主线程期待超时。
- 系统资源被占用(占比14%):其余过程系统资源(CPU/RAM/IO)占用率高,导致该过程无奈抢占到足够的系统资源。
- 主线程耗时工作导致线程卡死(占比9%):例如大量的数据库读写,耗时的网络状况,高强度的硬件计算等。
2、解决ANR问题方法论
2.1 总体思路
- 导出ANR日志信息,依据日志信息,判断确认产生ANR的包名类名,过程号,产生工夫,导致ANR起因类型等。
- 关注系统资源信息,包含ANR产生前后的CPU,内存,IO等系统资源的应用状况。
- 查看主线程状态,关注主线程是否存在耗时、死锁、等锁等问题,判断该ANR是App导致还是零碎导致的。
- 联合利用日志,代码或源码等,剖析ANR问题产生前,利用是否有异样,其中具体问题具体分析。
2.2 导出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>
2.3 读取要害日志信息
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的占用状况。
2.4 具体分析
剖析CPU usage当前,如若还是无奈找出问题起因,则须要进一步剖析trace文件。traces文件中具体记录了产生ANR前后该过程的各个线程的Stack,个别从主线程的stack动手剖析,查看剖析ANR问题产生前,利用是否有异样。
其中不同场景下的ANR问题状况不大雷同,须要具体情况具体分析,此处就不开展详细描述。
3、ANR问题难点及破题思路
3.1 ANR难点
用户在利用内的绝大部分操作,比方按钮点击,加载资源,页面跳转等操作,都须要有App的被动反馈,但ANR产生时,在用户期待数秒后,仅会弹出一个“利用无响应”的弹窗给用户,这会给用户带来“利用难用”的感觉,极其影响用户体验。
然而,现网中的ANR问题又很难解决,问题包含但不限于:
- 平时的测试难以笼罩,毕竟ANR经常出现在老设施、弱网络环境的场景下,测试难以做到全场景笼罩。
对于现网利用的ANR问题,如果问题非必现,则定位难度较高,须要有能够复现问题的理论设施在身边,能力获取到具体日志trace等信息。
- ANR问题定位简单,影响因素多,一些新负责定位ANR问题的同学,上手艰难,问题解决比拟依赖教训。
3.2 ANR解决新计划
除了依赖现有传统的ANR问题定位教训,配合第三方利用监控平台、进行ANR问题的解决,也是方便快捷的ANR解决伎俩。
晋升用户体验火烧眉毛,但ANR问题对用户体验影响大, 定位解决ANR问题老大难,针对这个需要痛点,越来愈多的第三方开始钻研并对外提供利用性能监控工具。
性能治理(App Performance Management,简称APM)是华为AppGallery Connect品质系列服务中的其中一项,提供分钟级利用性能监控能力,其ANR剖析性能,更是解决ANR问题定位与解决的最佳搭档。应用AGC性能治理服务监控利用ANR,可能为您带来以下益处:
1.实时监控现网利用ANR,现网利用ANR趋势全把握。
2.ANR现场信息主动采集和展现,大部分状况无需复现,在线定位问题。
3.通过APM页面,定位思路系统化,疾速上手ANR问题定位,及时解决问题。
4、ANR问题解决案例整顿
接下来以华为AGC性能治理服务为例,介绍配合AGC性能治理服务,如何疾速定位典型的ANR问题。
4.1 案例(一):死锁导致的ANR问题定位
4.1.1 发现问题
在华为AGC控制台的我的我的项目-品质-性能治理页面,在“ANR剖析”页签下,发现排在第一位的“用户ANR率”高达16.67%,决定优先解决该类ANR问题。
4.1.2 定位问题
点开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问题的具体起因:异样场景导致锁资源未被开释,从而造成了主线程呈现死锁。
4.1.3 解决问题
为了修复了该问题,咱们做了以下措施,解决该问题的同时,预防同类问题产生:
- 剖析异样具体起因并批改代码,避免越界异样再次出现。
- 捕捉该异样,爱护代码在资源开释前被异样抛出。
- 排查其余代码,在资源开释前,加上爱护,保障资源及时开释。
4.2 案例(二):IO资源有余导致ANR问题定位
4.2.1 定位问题
直奔问题外围,间接进入“单次ANR问题” 页面,去剖析问题,强化咱们借助性能治理服务定位ANR问题思路。 
(1)剖析系统资源状态.
首先,通过报告,发现该问题产生时,CPU占用是100%、IO占用是84%、未产生过低内存、利用被调配堆是26.50MB、利用已用堆是8.69MB,从系统资源来看,CPU占用和IO占用呈现显著异样,如下图所示:
由定位大部分ANR问题教训可知,该ANR问题是因为系统资源有余导致,那么剖析该ANR问题思路为:找到本身应用程序ANR代码片段,剖析否可能优化代码,在高IO状况下,不触发ANR。
(2)查看主线程状态:发现问题起因
咱们切换到“主线程堆栈”页签,察看主线程代码。
通过观察主线程堆栈,咱们发现了一个存在问题的中央,主线程外面间接在做数据库操作,在零碎IO高的状况,此操作必定会导致主线程被阻塞。咱们通过堆栈找到对应的代码。
由此咱们确认,在代码中存在拜访SQLite的操作。这时候有教训的开发者曾经晓得,问题可能通过优化解决,仅须要将该IO操作放在线程中执行即可。
(3) 查看利用日志
曾经在上一环节剖析出ANR起因,无需此步骤。
4.2.2 解决问题
咱们做了以下措施,优化了该问题代码,预防ANR问题产生。
4.3 案例(三):主线程死循环导致ANR问题定位
4.3.1 定位问题
话不多说,间接到“单次ANR问题”,固化问题定位思路。
(1)首先,通过报告,发现该问题产生时,CPU占用是25%、IO占用是0%、未产生过低内存、利用被调配堆是18.01MB、利用已用堆是8.08MB,线程数是43,从系统资源来看,均未呈现显著异样,如下图所示:
由定位大部分ANR问题教训可知,该ANR问题大概率不是因为系统资源有余导致,那么剖析该ANR问题思路转变为:该ANR问题由本身代码逻辑导致,接下来,咱们顺着该思路剖析这次的ANR问题。
(2)查看主线程状态:发现问题起因
本身代码逻辑导致ANR问题,其次要剖析思路是查看主线程堆栈及线程状态,咱们在性能治理页面上“主线程堆栈”页签中可能找到问题堆栈。
发现该问题产生时,发现主线程堆栈在getActivity中被阻塞,主线程处于“SUSPENDED”状态。这时咱们通过堆栈,找到问题代码。
通过代码剖析,狐疑主线程在该处呈现死循环。咱们晓得如果应用程序呈现死循环会导致应用程序的CPU用户态工夫占用异样升高,咱们晓得“ANR信息”页签中记录了ANR产生时的各过程的CPU占用信息,于是咱们在页面上切换到“ANR信息”页签。
咱们在“ANR信息”页签中发现,本身应用程序CPU用户态的资源占用达到了94%,因而验证了咱们之前的猜测:主线程呈现了死循环,导致了ANR问题。
(3)查看利用日志
曾经在上一环节剖析出ANR起因,无需此步骤。
4.3.2 解决问题
咱们做了以下措施,优化了该问题代码,预防ANR问题产生。
5、案例总结
以上ANR问题的解决与解决,都是配合华为AppGallery Connect性能治理治理服务实现的,其中的ANR问题剖析报告,ANR问题产生时的问题记录,都由AGC性能治理服务界面所提供。
通过AGC性能服务里的 ANR剖析详情 能够查看产生某类ANR问题时的趋势及散布信息,其中包含按利用版本版本散布,按手机型号散布,按零碎版本散布和问题产生的实时走势。帮忙剖析这一类ANR问题对用户的影响趋势,以及问题复现条件。
另外开发者能够通过具体的问题产生记录,获取到该问题产生时更加具体的设施信息,零碎信息,利用信息和堆栈日志,帮忙开发者疾速定位该问题。
6、相干链接
- AGC性能治理服务的超简略集成,能够参考该文章:https://developer.huawei.com/...
- AGC性能治理服务官网文档,可参考:https://developer.huawei.com/...