ANR的理论_anr概念/类型/原理/机制

一:什么是anr

ANR(Application Not Responding) 应用程序无响应。如果你应用程序在UI线程被阻塞太长时间,就会出现ANR,通常出现ANR,系统会弹出一个提示提示框,让用户知道。

二:anr 类型

1.KeyDispatchTimeout: input事件在5S内没有处理完成发生了ANR。

logcat日志关键字:Input event dispatching timed out

2.BroadcastTimeout

前台Broadcast:onReceiver在10S内没有处理完成发生ANR。

后台Broadcast:onReceiver在60s内没有处理完成发生ANR。

logcat日志关键字:Timeout of broadcast BroadcastRecord

3. ServiceTimeout

前台Service:onCreate,onStart,onBind等生命周期在20s内没有处理完成发生ANR。

后台Service:onCreate,onStart,onBind等生命周期在200s内没有处理完成发生ANR

logcat日志关键字:Timeout executing service

4.ContentProviderTimeout ContentProvider 在10S内没有处理完成发生ANR。

logcat日志关键字:timeout publishing content providers

三:anr 触发机制

ANR 是一套监控 Android 应用响应是否及时的机制,可以把发生 ANR 比作是引爆炸弹,那么整个流程包含三部分组成:
1. 启动 定时炸弹:中控系统 (system_server 进程 ) 启动倒计时,在规定时间内如果目标 ( 应用进程 ) 没有干完所有的活,则中控系统会定向炸毁( 杀进程 ) 目标。
2. 拆炸弹:在规定的时间内干完工地的所有活,并及时向中控系统报告完成,请求解除定时炸弹,则幸免于难。
3. 引爆炸弹:中控系统立即封装现场,抓取快照,搜集目标执行慢的罪证 (traces) ,便于后续的案件侦破 ( 调试分析) ,最后是炸毁目标。
举例:用户点击按钮,中控系统启动定时炸弹; 点击按钮后,执行的事务,在规定的5s内完成了,则解除了定时炸弹;如果点击按钮,发现点击按钮做的事务在执行了5s,后还没有结束,然后又有别的输入事件,这个时候,就会引爆炸弹。

service超时机制

1. 客户端 (App 进程 ) 向中控系统 (system_server 进程 ) 发起启动服务的请求
2. 中控系统派出一名空闲的通信员 (binder_1 线程 ) 接收该请求,紧接着向组件管家 (ActivityManager 线程 ) 发送消 息,埋下定时炸弹
3. 通讯员 1 (binder_1) 通知工地 (service 所在进程 ) 的通信员准备开始干活
4. 通讯员 3 (binder_3) 收到任务后转交给包工头 (main 主线程 ) ,加入包工头的任务队列 (MessageQueue)
5. 包工头经过一番努力干完活 ( 完成 service 启动的生命周期 ) ,然后等待 SharedPreferences( 简称 SP) 的持久化;
6. 包工头在 SP 执行完成后,立刻向中控系统汇报工作已完成
7. 中控系统的通讯员 2 (binder_2) 收到包工头的完工汇报后,立刻去拆除炸弹。如果在炸弹定时结束前拆除炸弹 则拆除炸弹,否则会引发爆炸( 触发 ANR)

broadcast超时机制

对于静态注册的广播在超时检测过程需要检测 SP ,如下图所示
1. 客户端 (App 进程 ) 向中控系统 (system_server 进程 ) 发起发送广播的请求
2. 中控系统派出一名空闲的通信员 (binder_1) 接收该请求转交给组件管家 (ActivityManager 线程 )
3. 组件管家执行任务 (processNextBroadcast 方法 ) 的过程埋下定时炸弹
4. 组件管家通知工地 (receiver 所在进程 ) 的通信员准备开始干活
5. 通讯员 3 (binder_3) 收到任务后转交给包工头 (main 主线程 ) ,加入包工头的任务队列 (MessageQueue)
6. 包工头经过一番努力干完活 ( 完成 receiver 启动的生命周期 ) ,发现当前进程还有 SP 正在执行写入文件的操作,便将向中控系统汇报的任务交给SP 工人 (queued-work-looper 线程 )
7. SP 工人历经艰辛终于完成 SP 数据的持久化工作,便可以向中控系统汇报工作完成
8. 中控系统的通讯员 2 (binder_2) 收到包工头的完工汇报后,立刻去拆除炸弹。如果在倒计时结束前拆除炸弹则炸弹拆除,否则会引发爆炸( 触发 ANR)。

SP 8.0 开始采用名叫 “queued-work-looper” handler 线程,在老版本采用 newSingleThreadExecutor 创 建的单线程的线程池)
如果是动态广播,或者静态广播没有正在执行持久化操作的 SP 任务,则不需要经过 “queued-work-looper” 线程中 转,而是直接向中控系统汇报,流程更为简单,如下图所示:

 provider超时机制

provider 的超时是在 provider 进程 首次启动的时候 才会检测,当 provider 进程已启动的场景,再次请求 provider 并不会触发provider 超时。
1. 客户端 (App 进程 ) 向中控系统 (system_server 进程 ) 发起获取内容提供者的请求
2. 中控系统派出一名空闲的通信员 (binder_1) 接收该请求,检测到内容提供者尚未启动,则先通过 zygote 孵化新进程
3. 新孵化的 provider 进程向中控系统注册自己的存在
4. 中控系统的通信员 2 号接收到该信息后,向组件管家 (ActivityManager 线程 ) 发送消息,埋下炸弹
5. 通信员 2 号通知工地 (provider 进程 ) 的通信员准备开始干活
6. 通讯员 4 (binder_4) 收到任务后转交给包工头 (main 主线程 ) ,加入包工头的任务队列 (MessageQueue)
7. 包工头经过一番努力干完活 ( 完成 provider 的安装工作 ) 后向中控系统汇报工作已完成
8. 中控系统的通讯员 3 (binder_3) 收到包工头的完工汇报后,立刻去拆除炸弹。如果在倒计时结束前拆除炸弹则拆除炸弹,否则会引发爆炸( 触发 ANR).

input超时机制

input 的超时检测机制跟 service broadcast provider 截然不同,为了更好的理解 input 过程先来介绍两个重要线程的相关工作:
1.InputReader 线程: 负责通过 EventHub( 监听目录 /dev/input) 读取输入事件,一旦监听到输入事件则放入到InputDispatcher的 mInBoundQueue 队列,并通知其处理该事件;
2.InputDispatcher 线程: 负责将接收到的输入事件分发给目标应用窗口,分发过程使用到 3 个事件队列:
   a.  mInBoundQueue 用于记录 InputReader 发送过来的输入事件;
   b. outBoundQueue 用于记录即将分发给目标应用窗口的输入事件;
   c. waitQueue 用于记录已分发给目标应用,且应用尚未处理完成的输入事件;
input的超时机制并非时间到了一定就会爆炸,而是处理再次有上报输入事件的过程才会去检测是否该爆炸,具体如下图所示。

四:为什么会出现ANR

1:主线程频繁进行耗时的IO操作:如数据库读写

2:多线程操作的死锁,主线程被block;(搜索关键字 held by)

3:主线程被Binder 对端block;

4:System Server中WatchDog出现ANR;

5:service binder的连接达到上线无法和和System Server通信

6:系统资源已耗尽(管道、CPU、IO)

五:ANR 实例分析

主要分析:通过logcat日志或者traces文件确认anr发生时间点; CPU使用率 ;主线程状态;其他线程状态

1,看anr日志,主要了解发生anr的进程等信息

2. 看主线程(下面是一个线程死锁的例子)

 主线程执行了耗时操作

六,参数分析

main:main标识是主线程,如果是线程,那么命名成“Thread-X”的格式,x表示线程id,逐步递增。 prio:线程优先级,默认是5

tid:tid不是线程的id,是线程唯一标识ID

group:是线程组名称

sCount:该线程被挂起的次数

dsCount:是线程被调试器挂起的次数

obj:对象地址

self:该线程Native的地址

sysTid:是线程号(主线程的线程号和进程号相同)

nice:是线程的调度优先级

sched:分别标志了线程的调度策略和优先级

cgrp:调度归属组

handle:线程处理函数的地址。

state:是调度状态

schedstat:从 /proc/[pid]/task/[tid]/schedstat读出,三个值分别表示线程在cpu上执行的时间、线程的等待时间和线程执行的时间片长度,不支持这项信息的三个值都是0; utm:是线程用户态下使用的时间值(单位是jiffies)

stm:是内核态下的调度时间值

core:是最后执行这个线程的cpu核的序号

七:分析步骤

1).收集的信息如下

前台 ANR 发生后,系统会马上去抓取现场的信息,用于调试分析,收集的信息如下 :

a.  将am_anr信息输出到EventLog,也就是说ANR触发的时间点最接近的就是EventLog中输出的am_anr信 息

b. 收集以下重要进程的各个线程调用栈trace信息,保存在data/anr/traces.txt文件

b1. 当前发生 ANR 的进程, system_server 进程以及所有 persistent 进程
b2. audioserver, cameraserver, mediaserver, surfaceflflinger 等重要的 native 进程
b3. CPU 使用率排名前 5 的进程

c. 将发生ANRreason以及CPU使用情况信息输出到main log

c1. 将 traces 文件和 CPU 使用情况信息保存到 dropbox ,即 data/system/dropbox 目录
c2. 对用户可感知的进程则弹出 ANR 对话框告知用户,对用户不可感知的进程发生 ANR 则直接杀掉

2). 分析步骤

1. 定位发生 ANR 时间点
2. 查看 trace 信息
3. 分析是否有耗时的 message,binder 调用,锁的竞争, CPU 资源的抢占
4. 结合具体的业务场景的上下文来分析
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值