ANR(Application Not responding),是指应用程序未响应,Android系统对于一些事件需要在一定的时间范围内完成,如果超过预定时间能未能得到有效响应或者响应时间过长,都会造成ANR。一般地,这时往往会弹出一个提示框,告知用户当前xxx未响应,用户可选择继续等待或者Force Close。
ANR的时间
Service Timeout:比如前台服务在20s内未执行完成,后台Service是200s;
BroadcastQueue Timeout:比如前台广播在10s内未执行完成,后台BroadcastReceiver是60s
ContentProvider Timeout:内容提供者,在publish过超时10s;
InputDispatching Timeout: 输入事件分发超时5s,包括按键和触摸事件。
出现的场景
- 应用在主线程上非常缓慢地执行涉及I/O的操作
- 应用在主线程上进行长时间的计算
- 主线程在对另一个进程进行同步binder,而后面需要很长时间才能返回
- 主线程被阻塞,等待另一个线程上正在进行的长时间操作的同步块
怎么去排查ANR问题
使用Strict mode
StrictMode可以帮助您在开发应用程序时在主线程上查找意外的I / O操作
使用traces 文件
当遇到ANR时,Android会存储跟踪信息。在较旧的OS版本上,设备上只有一个/data/anr/traces.txt文件。在较新的OS发行版中,存在多个/ data / anr / anr_ *文件, 使用下面工具导出ANR日记
adb shell bugreport > log_file_name_to_save.txt。
打开对应的文件,类似会下面格式:
....
"main" prio=5 tid=1 Blocked
| group="main" sCount=1 dsCount=0 flags=1 obj=0x71df12f8 self=0x7e7de10800
| sysTid=12750 nice=-10 cgrp=default sched=1073741825/1 handle=0x7f04c22ed0
| state=S schedstat=( 912713528 81383848 2003 ) utm=67 stm=23 core=4 HZ=100
| stack=0x7fc9a10000-0x7fc9a12000 stackSize=8192KB
| held mutexes=
at com.globalegrow.app.gearbest.support.network.f.a(HttpManager.java:-1)
- waiting to lock <0x09bbae37> (a
package.name.support.network.f) held by thread 4
...
根据thread名字可以查找对应的进程,搜索main就会定位到上面的日记
字段解析
- 线程名(如有daemon则代表守护线程),main表示主线程
- prio: 线程优先级
- tid: 线程号
- 线程当前状态: Blocked表示主线程阻塞了,我这里出现的情况就是等待另一个线程上正在进行的长时间操作(网络请求),而且这个网络请求的方式前面加了Synchronized同步
- mutex: 所持有mutex类型,有独占锁exclusive和共享锁shared两类
使用CPU Profiler overview
CPU Profiler 的默认视图包括以下时间轴:
- 事件时间轴:显示应用中的 Activity 在其生命周期内不断转换而经历各种不同状态的过程,并指示用户与设备的交互,包括屏幕旋转事件。如需了解如何在搭载 Android 7.1(API 级别 25)及更低版本的设备上启用事件时间轴,请参阅启用高级分析。
- CPU 时间轴:显示应用的实时 CPU 使用率(以占总可用 CPU 时间的百分比表示)以及应用当前使用的线程总数。 此时间轴还会显示其他进程(如系统进程或其他应用)的 CPU 使用率,以便您可以将其与您应用的 CPU 使用率进行对比。您可以通过沿时间轴的横轴方向移动鼠标来检查历史 CPU 使用率数据。
- 线程活动时间轴:列出属于应用进程的每个线程,并使用下面列出的颜色在时间轴上指示它们的活动。记录跟踪数据后,您可以从此时间轴上选择一个线程,以在跟踪数据窗格中检查其数据。
- 绿色:表示线程处于活动状态或准备使用 CPU。也就是说,线程处于正在运行或可运行状态。
- 黄色:表示线程处于活动状态,但它正在等待一项 I/O 操作(如磁盘或网络 I/O),然后才能完成它的工作。
- 灰色:表示线程处于休眠状态并且没有占用任何 CPU 时间。 当线程需要访问尚不可用的资源时,就会出现这种情况。在这种情况下,要么线程主动进入休眠状态,要么内核将线程置于休眠状态,直到所需的资源可用
Call Chart 标签页会以图形来呈现方法跟踪数据或函数跟踪数据,其中调用的时间段和时间在横轴上表示,而其被调用方则在纵轴上显示, 对系统 API 的调用显示为橙色,对应用自有方法的调用显示为绿色,对第三方 API(包括 Java 语言 API)的调用显示为蓝色
这里主要是看主线程上Java api调用时长来找到具体是怎么操作耗时了引起ANR的