关于android:Android-ANR全解析华为AGC性能管理解决ANR案例集

39次阅读

共计 6521 个字符,预计需要花费 17 分钟才能阅读完成。

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 总体思路

  1. 导出 ANR 日志信息,依据日志信息,判断确认产生 ANR 的包名类名,过程号,产生工夫,导致 ANR 起因类型等。
  2. 关注系统资源信息,包含 ANR 产生前后的 CPU,内存,IO 等系统资源的应用状况。
  3. 查看主线程状态,关注主线程是否存在耗时、死锁、等锁等问题,判断该 ANR 是 App 导致还是零碎导致的。
  4. 联合利用日志,代码或源码等,剖析 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 问题又很难解决,问题包含但不限于:

  1. 平时的测试难以笼罩,毕竟 ANR 经常出现在老设施、弱网络环境的场景下,测试难以做到全场景笼罩。
  2. 对于现网利用的 ANR 问题,如果问题非必现,则定位难度较高,须要有能够复现问题的理论设施在身边,能力获取到具体日志 trace 等信息。

    1. 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。![在这里插入图片形容](https://img-blog.csdnimg.cn/20201019140602440.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDcwODI0MA==,size_16,color_FFFFFF,t_70#pic_center)

查看具体的堆栈信息,咱们找到了 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 解决问题
为了修复了该问题,咱们做了以下措施,解决该问题的同时,预防同类问题产生:

  1. 剖析异样具体起因并批改代码,避免越界异样再次出现。
  2. 捕捉该异样,爱护代码在资源开释前被异样抛出。
  3. 排查其余代码,在资源开释前,加上爱护,保障资源及时开释。

4.2 案例(二):IO 资源有余导致 ANR 问题定位

4.2.1 定位问题

 直奔问题外围,间接进入“单次 ANR 问题”页面,去剖析问题,强化咱们借助性能治理服务定位 ANR 问题思路。![在这里插入图片形容](https://img-blog.csdnimg.cn/20201019141007404.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDcwODI0MA==,size_16,color_FFFFFF,t_70#pic_center)

(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/…

正文完
 0