Android ANR 原理浅析

文章目录

    • [一、ANR 概述](#一、ANR 概述)
    • [二、ANR 的三种类型及触发条件](#二、ANR 的三种类型及触发条件)
    • [三、ANR 的核心原理(重点)](#三、ANR 的核心原理(重点))
      • [3.1 Input ANR 机制](#3.1 Input ANR 机制)
      • [3.2 Service/Broadcast ANR 机制](#3.2 Service/Broadcast ANR 机制)
      • [3.3 主线程阻塞的底层原因](#3.3 主线程阻塞的底层原因)
    • [四、ANR 的触发流程(源码级别)](#四、ANR 的触发流程(源码级别))
    • [五、ANR 的排查思路(面试加分项)](#五、ANR 的排查思路(面试加分项))
    • [六、常见导致 ANR 的编码错误(面试应答示例)](#六、常见导致 ANR 的编码错误(面试应答示例))
    • 七、优化与预防(展示工程能力)
    • 八、面试中可能遇到的追问
    • 九、总结一句话(面试金句)
    • 十、扩展阅读

一、ANR 概述

定义:ANR(Application Not Responding)即应用无响应,当应用的主线程在特定时间内未能处理完某个事件时,系统弹出的对话框。

核心原因:主线程被阻塞,无法及时响应输入事件或组件生命周期回调。

二、ANR 的三种类型及触发条件

类型 触发场景 超时时间 关键组件
Input ANR 按键/触摸事件未响应 5秒 InputDispatcher
Service ANR Service 启动/绑定超时 20秒(前台)/ 200秒(后台) ActivityManagerService
Broadcast ANR 广播接收者 onReceive 未执行完 10秒 BroadcastQueue
ContentProvider ANR ContentProvider 发布超时 10秒 ContentProviderPublisher

注:Android 12 后对后台广播限制更严,前台广播超时仍为 10 秒。

三、ANR 的核心原理(重点)

3.1 Input ANR 机制

  • InputDispatcher 负责分发输入事件,会记录每个事件的开始时间。
  • 事件发送给应用主线程后,主线程通过 Looper 循环处理。
  • 如果事件处理完成后,应用未在 5 秒内 通知 InputDispatcher 处理完成,InputDispatcher 会检查应用主线程是否阻塞。
  • 阻塞判定:inputDispatchingTimeout 超时 && 应用主线程正在处理上一个事件或处于等待状态 → 触发 ANR。

3.2 Service/Broadcast ANR 机制

  • AMS 在启动 Service 或发送广播时,会通过 Handler 发送一个延时消息(超时消息)。
  • 如果组件在超时前正常完成,会移除该延时消息。
  • 超时消息到时触发,AMS 检查组件状态 → 若未完成 → 触发 ANR。

源码关键路径

  • ActiveServices.scheduleServiceTimeoutLocked()SERVICE_TIMEOUT_MSG
  • BroadcastQueue.processNextBroadcast()BROADCAST_TIMEOUT_MSG

3.3 主线程阻塞的底层原因

Android 应用运行基于 消息驱动模型(MessageQueue + Looper)。主线程不断从 MessageQueue 中取消息执行。如果某消息执行耗时过长,后续消息(包括触摸事件、生命周期的下一动作)无法及时处理,就会导致 ANR。

四、ANR 的触发流程(源码级别)

  1. 系统服务(AMS/InputDispatcher)检测到超时。
  2. 调用 appNotResponding() 方法。
  3. 收集进程状态:主线程堆栈(traces.txt)、CPU 使用情况、内存信息。
  4. 向 SystemServer 中的 Watchdog 报告。
  5. 弹出 ANR 对话框(或后台直接杀进程,取决于场景)。

五、ANR 的排查思路(面试加分项)

步骤 操作 关键命令/文件
1 抓取 ANR 日志 adb pull /data/anr/traces.txt
2 查看主线程堆栈 搜索 "main" prio= 找到主线程,关注 waitingsleepingmonitor 状态
3 确认 ANR 类型 从 logcat 中搜索 ANR inInput dispatching timed out
4 分析卡顿点 堆栈中的业务代码行号,定位耗时操作
5 系统负载检查 logcat 中搜索 CPU usageload average

六、常见导致 ANR 的编码错误(面试应答示例)

  • ❌ 主线程直接执行网络请求、数据库批量操作
  • ❌ 主线程持有锁并等待子线程的某个条件(死锁)
  • ❌ 使用 Thread.sleep()wait() 在主线程
  • ❌ BroadcastReceiver 的 onReceive() 中执行耗时操作(应使用 goAsync() 或启动 Service)
  • ❌ 多进程下的 ContentProvider 调用在主线程同步等待

七、优化与预防(展示工程能力)

  • 使用 StrictMode 检测主线程 IO/网络
  • 异步处理:AsyncTask(已废弃)、HandlerThreadCoroutines
  • 启动优化:延迟初始化、Application.onCreate 轻量化
  • 使用 Systrace / Perfetto 分析主线程卡顿点
  • 采用 ViewStub、异步 Inflate 优化布局加载

八、面试中可能遇到的追问

Q1:ANR 和 Crash 的区别?

  • Crash 是未捕获异常导致进程中止;ANR 是进程活着但无响应,系统会弹框让用户选择「等待」或「关闭」。

Q2:能否避免 ANR 对话框弹出?

  • 不能完全避免,但可以通过优化保证应用始终响应。系统设置的 ANR 弹框默认开启,但车机场景可通过 Settings.Global.ANR_SHOW_NOTIFICATION 等配置关闭(需系统权限)。

Q3:Service 的 ANR 超时时间为什么比 Broadcast 长?

  • Service 通常是后台长时间运行操作,允许更长的启动时间;Broadcast 期望快速完成(沾到主线程),超时更短。

Q4:traces.txt 文件中没有主线程堆栈怎么办?

  • 尝试手动抓取:adb shell kill -3 <pid> 生成当前线程堆栈。如果依然没有,可能是进程已死或权限问题。

九、总结一句话(面试金句)

ANR 是 Android 系统为保证应用响应性而设计的软限流机制,本质是主线程阻塞导致消息处理超时,通过 InputDispatcherAMS 的延时消息机制触发,排查的核心是分析 /data/anr/traces.txt 中的主线程调用栈。


建议背诵:类型、超时时间、触发机制、排查命令、常见原因。结合一两个实际项目中的 ANR 案例说明会更出彩。

十、扩展阅读

理解Android ANR的触发原理

分析路线:触发ANR的过程可分为三个步骤: 埋炸弹, 拆炸弹, 引爆炸弹

相关推荐
乐兮创想 小林6 小时前
企业官网移动端性能优化实战:从 Core Web Vitals 到图片/CDN/响应式的工程清单
前端·性能优化·网站建设·北京网站建设公司
故渊at11 小时前
第二板块:Android 四大组件标准化学理 | 第六篇:四大组件架构总论与 Manifest 规范
android·架构·zygote·manifest·四大组件
Jinkxs11 小时前
Python基础 - 文件的写入操作 write与writelines方法
android·服务器·python
jason.zeng@150220711 小时前
(第二讲)Android开发取摄像头流的基础(ImageAnalysis)
android
兮动人12 小时前
服务器流量监控与性能优化实战
服务器·网络·性能优化·服务器流量监控与性能优化实战
敲代码的瓦龙12 小时前
操作系统?Android与Linux!!!
android·linux·运维
愚公搬代码13 小时前
【愚公系列】《移动端AI应用开发》017-Android端应用开发(网络通信与API集成)
android·人工智能
say_fall13 小时前
可编程中断控制器8259A工作方式超详细解析
android·开发语言·学习·硬件架构·硬件工程
甜瓜看代码14 小时前
SystemUI 启动与组成机制
android·源码·源码阅读
黄林晴15 小时前
Kotlin 2.4.0 正式稳定!Android 升级、Compose、KMP 全变化详解
android·kotlin