1. 什么是ANR
ANR(Application Not responding),是指应用程序未响应,Android系统对于一些事件需要在一定的时间范围内完成,如果超过预定时间能未能得到有效响应或者响应时间过长,都会造成ANR。
2. 什么场景产生ANR
- Service Timeout: 前台服务在20s内未执行完成,后台服务200s内未执行完成。
- BroadcastQueue Timeout:前台广播在10s内未执行完成,后台广播在60s内未执行完成。
- ContentProvider Timeout:内容提供者,publish超时10s未完成。
- InputDispatching Timeout: 输入事件分发超时5s,包括按键和触摸事件。
3. 什么原因导致ANR
应用层导致ANR:
- 函数阻塞:如死循环、主线程IO、处理大数据。
- 锁出错:主线程等待子线程的锁。
- 内存紧张:系统分配给一个应用的内存是有上限的,长期处于内存紧张,会导致频繁内存交换,进而导致应用的一些操作超时。
系统导致ANR:
- CPU被抢占:一般来说,前台在玩游戏,可能会导致你的后台广播被抢占。
- 系统服务无法及时响应:比如获取系统联系人等,系统的服务都是Binder机制,服务能力也是有限的,有可能系统服务长时间不响应导致ANR。
- 其他应用占用大量内存
4. ANR dump主要流程
ANR流程基本是在system_server系统进程完成的,系统进程的行为我们很难监控到,想要监控就得从系统进程与应用进程沟通的边界着手,看边界上有没有可以操作的地方。
不管是怎么发生的ANR,最后都会走到appNotResponding ,比如输入超时的路径。
ActivityManagerService#inputDispatchingTimedOut
AnrHelper#appNotResponding
AnrConsumerThread#run
AnrRecord#appNotResponding
ProcessRecord#appNotResponding
5. 线上监控方案
- 通过 FileOberver 监控上述的ANR信息文件的变化, 如果这个文件发生了变化,那就说明发生了ANR, 那便可以把它上报到服务器,进行详细的分析【高版本需注意权限问题】。
- 集成 ANR WatchDog
原理:启动一个异步线程,在while循环中,使用主线程的Handler发送一个消息,线程休眠指定的时间5s,当线程唤醒之后,如果发送的消息还没被主线程执行,即认为主线程发生了卡顿。
- SIGQUIT信号监控
通过拦截SIGQUIT来判断系统是否向进程发送信号
收到SIGQUIT后,判断主线程是否block,如果主线程block,上报ANR
循环获取App ErrorState,如果状态变成NOT_RESPONDING,上报ANR