写在前面
ANR 问题,对于从事 Android 开发的同学来说并不陌生,日常开发中,经常会遇到应用乃至系统层面引起的各种问题,很多时候因为不了解其运行原理,在面对该类问题时可能会一头雾水。与此同时,因为现有监控能力不足或获取信息有限,使得这类问题如同镜中花水中月,让我们在追求真理的道路上举步维艰。如下图:

工作中在帮助大家分析问题时,发现有不少同学问到,在哪里可以更加系统的学习?于是本人抱着“授人以鱼,不如授人以渔”的态度,结合个人理解和工作实践,接下来将从设计原理、影响要素、工具建设、分析思路,案例实战、优化探索等几个篇章,对 ANR 方向进行一次全面的总结,希望帮助大家在今后的工作中更好地理解和应对以下问题:
什么是 ANR?
系统是如何设计 ANR 的?
发生 ANR 时系统都会获取哪些信息以及工作流程?
导致 ANR 的原因有哪些?
遇到这类问题该如何分析?
如何能更加快速准确的定位问题?
面对这类问题我们能主动做些什么?
简述
在正式分析 ANR 问题之前,先来看看下面这些问题:
系统是如何设计 ANR 的,都有哪些服务或者组件会发生 ANR?
发生 ANR 的时候,系统又是如何工作的,都会获取哪些信息?
影响 ANR 的场景有哪些?我们是如何对其进行归类的?
了解这些有助于我们在面对各种问题时,做到有的放矢,下面我们就来介绍并回答这些问题。
ANR 设计原理
ANR 全称 Applicatipon No Response;Android 设计 ANR 的用意,是系统通过与之交互的组件(Activity,Service,Receiver,Provider)以及用户交互(InputEvent)进行超时监控,以判断应用进程(主线程)是否存在卡死或响应过慢的问题,通俗来说就是很多系统中看门狗(watchdog)的设计思想。
组件超时分类
系统在通过 Binder 通信向应用进程发送上述组件消息或 Input 事件时,在 AMS 或 Input 服务端同时设置一个异步超时监控。当然针对不同类型事件,设置的超时时长也存在差别,以下是 Android 系统对不同类型的超时阈值设置:
(图片仅供参考,国内厂商可能会有调整,每个厂商的标准也存在差异)
Broadcast 超时原理举例
在了解不同类型消息的超时阈值之后,我们再来了解一下超时监控的设计原理。
以 BroadCastReceiver 广播接收超时为例,广播分为有序广播和无序广播,同时又有前台广播和后台广播之分;只针对有序广播设置超时监控机制,并根据前台广播和后台广播的广播类型决定了超时时长;例如后台广播超时时长 60S,前台广播超时时长只有 10S; 下面我们结合代码实现来看一下广播消息的发送过程。
无序广播:
对于无序广播,系统在搜集所有接收者之后一次性全部发送完毕,如下图;

有序广播:
再来看一下有序广播的发送和接收逻辑,同样在系统 AMS 服务中,BoradCastQueue 获取当前正在发送的广播消息,并取出下一个广播接收者,更新发送时间戳,以此时间计算并设置超时时间(但是系统在此进行了一些优化处理,以避免每次广播正常接收后,都需要取消超时监控然后又重新设置,而是采用一种对齐的方式进行复用)。最后将该广播发送给接收者,接收到客户端的完成通知之后,再发送下一个,整个过程如此反复。

在客户端进程中,Binder 线程接收到 AMS 服务发送过来的广播消息之后,会将此消息进行封装成一个 Message,然后将 Message 发送到主线程消息队列(插入到消息队列当前时间节点的位置,也正是基于此类设计导致较多消息调度及时性的问题,后面我们将详细介绍),消息接收逻辑如下:

正常情况下,很多广播请求都会在客户端及时响应,然后通知到系统 AMS 服务取消本次超时监控。但是在部分业务场景或系统场景异常的情况下,发送的广播未及时调度,没有及时通知到系统服务,便会在系统服务侧触发超时,判定应用进程响应超时。AMS 响应超时代码逻辑如下:
final void broadcastTimeoutLocked(boolean fromMsg) {
......
long now = SystemClock.uptimeMillis();
BroadcastRecord r = mOrderedBroadcasts.get(0);
if (fromMsg) {
//我们刚才提到的时间对齐方式,避免频繁取消和设置消息超时
long timeoutTime = r.receiverTime + mTimeoutPeriod;
if (timeoutTime > now) {
setBroadcastTimeoutLocked(timeoutTime);
return;
}
}
......
......
Object curReceiver;
if (r.nextReceiver > 0) {
//获取当前超时广播接收者
&nb

本文深入探讨Android中的ANR问题,包括设计原理、影响因素、工具建设和优化策略等内容,旨在帮助开发者更好地理解ANR并有效应对。
最低0.47元/天 解锁文章
2万+





