当前位置: 首页 > article >正文

ANR学习

一、ANR 概述

ANR 是 Android 系统用于监控应用是否及时响应的关键机制。形象地说,如同设置定时炸弹场景:系统的中控系统(system_server 进程)启动倒计时,若应用进程在规定时间内未完成特定任务,中控系统将触发 ANR,采取杀进程等措施;反之,若应用按时完成任务并向中控系统报告,炸弹则被拆除。触发 ANR 后,中控系统会封装现场、抓取快照(traces),以便后续排查问题根源。

二、四类超时机制

Service的ANR超时机制


图片流程解释
1.App进程向中控系统(system_server进程)发送启动服务请求
2.中控系统派发出一个通讯员(线程1)接收这个请求,然后转交给(ActivityManager),并安装定时炸弹
3.通讯员(线程1)通知目标阵营(Service进程)中的通讯员(线程3)让目标阵营开始做事
4.通讯员(线程3)将这个消息转达给做事的人(main),但是要排队(MessageQueue)。
5.经过努力,做事的人终于完成了事情(Service的启动的生命周期),然后开始等待SP持久化。
6.做事的人在做完事情后直接通知中控系统的负责接收的通信员(线程2),说明已经做完事情
7.通讯员(线程2)收到消息后,即刻拆除炸弹。如果此前操作超过时间阈值就来不及了。

SP持久化

它会将内存中的数据写入磁盘文件,并且会阻塞当前线程,直到数据成功写入或者写入失败。


与ANR关系
如果这个写入操作耗时过长,就会导致主线程被阻塞,无法及时处理其他消息和事件。当主线程阻塞时间超过系统设定的阈值(如用户输入事件 5 秒无响应、广播接收器 10 秒未处理完广播等),就会触发 ANR。

相关函数

commit() 方法
这是一个同步操作。调用 commit() 后,系统会将数据写入内存中的映射结构,并且会阻塞当前线程,直到数据成功写入磁盘文件或者写入失败。它会返回一个布尔值,表示写入是否成功。

apply() 方法
这是一个异步操作。调用 apply() 后,系统会将数据写入内存中的映射结构,并立即返回,不会阻塞当前线程。
然后,系统会在后台线程中异步地将数据写入磁盘文件。所以当你调用 apply() 后,不会立即完成持久化,可能需要等待一段时间。
通常推荐在主线程使用apply,因为异步执行不阻塞当前线程,但如果在一些特点场景下就不同了,比如下面的Broadcast的静态注册,它要求SP必须全部持久化到磁盘才能做其他的事情。在这种情况下如果过度使用apply会增大应用ANR的概率

Broadcast的ANR超时机制(静态注册)


图片流程解释
1.App进程向中控系统(system_server进程)发送广播请求
2.中控系统派发出一个通讯员(线程1)接收这个请求,然后转交给(ActivityManager)
3.(ActivityManager)来埋下定时炸弹
4.通讯员(线程1)通知目标阵营(Service进程)中的通讯员(线程3)让目标阵营开始做事
5.通讯员(线程3)将这个消息转达给做事的人(main),但是要排队(MessageQueue)。
6.经过努力,做事的人终于完成了事情(完成receiver启动的生命周期),但是SP正在执行文件操作,于是将汇报任务完成的工作交给了接盘侠(queued-work-looper线程)。
7.接盘侠终于完成了SP持久化的工作后,向中控系统汇报。
8.通讯员(线程2)收到消息后,即刻拆除炸弹。如果此前操作超过时间阈值就来不及了。
注意(如果是动态广播,或者静态广播没有正在执行持久化操作的SP任务,则不需要经过“queued-work-looper”线程中转,而是直接向中控系统汇报)


Provider的ANR超时机制


provider的超时是在provider进程首次启动的时候才会检测


图片流程解释
1.App进程向中控系统(system_server进程)发送内容提供者请求
2.中控系统派发出一个通讯员(线程1)接收这个请求,如果检测到内容提供者(provider),则先通过Zygote孵化进程
3.新孵化的provider进程向中控系统注册自己的存在
4.中控系统派发出一个通讯员(线程2)接收这个请求,然后转交给(ActivityManager),并安装定时炸弹
5.通讯员(线程2)通知目标阵营(Service进程)中的通讯员(线程4)让目标阵营开始做事
6.通讯员(线程3)将这个消息转达给做事的人(main),但是要排队(MessageQueue)。
7.经过努力,做事的人终于完成了事情(完成provider的安装工作)后直接向中控系统汇报事情已完成
8.通讯员(线程3)收到消息后,即刻拆除炸弹。如果此前操作超过时间阈值就来不及了。

Input的ANR超时机制


input变扫雷了


图片流程解释
1.Inputreader通过EventHub监听底层上报的输入事件,一旦收到输入事件就将其放到输入队列中,并唤醒InputDispatcher
2.InputReader会先检查是否有正在处理的事件,如果没有就从输入队列取出事件,并赋值给mPendingEvent,并且重置ANR的定时;否则不会取出事件,也不会重新定时。
然后检查窗口是否就绪,如果就绪条件满足其一就会进入扫雷(检查前一个正在处理的事件是否超时)
按键事件:输出队列和等待队列不为空
非按键:等待队列不为空,且等待队头超时500ms

如果满足就是终止,不满足就安全了进入3
3.将mPendingEvent转移到输出队列
4.当输出队列不为空,并且与应用通信管道连接正常,则从输出队列取出事件放到等待队列
5.inputdispatcher通过socket告知目标应用进程可以开始干活
6.App的做事的人(main)收到事件后,会转发到对应目标窗口
7.做事的人完成工作后,向中控系统汇报完成,中控系统会将事件从等待队列移除。

三、时间阈值

  • Input:用户输入操作时,应用 5 秒内未处理输入事件;输入法弹出或隐藏等操作超过 5 秒未完成。
  • Service:前台 Service 20 秒内未完成启动;后台 Service 200 秒内未完成启动;Service 的 onStartCommand 等方法执行耗时操作超相应时间限制。
  • Broadcast:静态注册的广播接收器 10 秒内未完成广播处理;动态注册的广播接收器执行 onReceive 方法耗时超 10 秒;有序广播中前一接收器处理时间过长阻塞广播传递。
  • Content Provider:query 操作因复杂查询、通信问题等超一定时间未返回结果;插入、更新、删除等操作因死锁、资源竞争等超系统设定时间阈值。10秒

http://www.kler.cn/a/543178.html

相关文章:

  • AI前端开发:赋能开发者,提升解决实际问题的能力
  • 探索RDMA技术:从基础到实践
  • DeepSeek渣机部署编程用的模型,边缘设备部署模型
  • 多机器人系统的大语言模型:综述
  • 中间件-安装Minio-集成使用(ubantu-docker)
  • DevOps的个人学习
  • 20250212:sigmastar系列1-获取UUID
  • Web项目测试专题(六)压力测试
  • IDEA中打包maven项目,提示Compilation failure
  • 政安晨的AI大模型训练实践 六 - open-webui vLLM 运行
  • python自动化测试之Pytest断言及Allure报告定制
  • 跟着李沐老师学习深度学习(七)
  • 三角测量——用相机运动估计特征点的空间位置
  • JavaSE基本知识补充 -Map集合
  • DeepSeek与核货宝订货系统的协同进化:智能商业范式重构
  • AI大模型介绍yolo
  • P5:使用pytorch实现运动鞋识别
  • 碰一碰发视频源码技术开发,支持OEM
  • 蓝桥杯 Java B 组之排序算法(冒泡、选择、插入排序)
  • 如何在VSCode中免费使用DeepSeek R1:本地大模型编程助手全攻略
  • Visual Studio 使用 “Ctrl + /”键设置注释和取消注释
  • 【问】强学如何支持 迁移学习呢?
  • 使用Python爬虫获取淘宝Custom API接口数据
  • 极坐标 径向位置
  • DataBase【MySQL基础夯实使用说明(中)】
  • 数据集笔记:SINPA 新加坡停车场数量数据集