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. 结合具体的业务场景的上下文来分析
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值