## 1. 什么是 ANR

ANR 全称：**Application Not Responding**，即**应用程序无响应**。

## 2. 触发条件

1. 只有 ** 主线程（UI 线程）** 才会产生 ANR。
2. 必须发生输入事件或特定组件操作：
    
    - 按键、触屏等输入事件
    - `BroadcastReceiver` 生命周期回调
    - `Service` 生命周期回调
    
3. 事件响应超时，不同场景超时时间不同。

### 2.1 各场景超时时间

- **Activity 输入事件 / 生命周期**：主线程 5s 内未处理完毕
- **BroadcastReceiver#onReceive()**：主线程 10s 内未处理完毕
- **Service 生命周期**：主线程 20s 内未处理完毕

## 3. ANR 根本原因

### 3.1 主线程执行耗时操作

典型场景：

- 耗时网络访问
- 大量数据读写、数据库操作
- 硬件操作（如 Camera）
- 多线程被 Binder 对端 block
- 主线程调用 `Thread.join()`/`sleep()`/`wait()`、等待线程锁
- Service Binder 数量达上限，无法与 System Server 通信
- System Server 中 WatchDog 导致 ANR、Service 繁忙超时

### 3.2 非主线程导致

非主线程持有锁，导致主线程等待锁超时 / 无限等待，最终触发 ANR。

### 3.3 其他进程 / 系统资源问题

- 其他进程占用 CPU，本进程得不到时间片
- 内存泄漏导致频繁 Full GC，CPU 占用飙升
- 内存吃紧、系统频繁 coredump

> CPU 利用率说明：
> 
> - 前台进程 ≤ 95%，后台进程 ≤ 5%（无前台时可超）
> - `RUNNABLE` 线程不一定耗 CPU
> - `TIMED_WAITING`/`WAITING` 线程不耗 CPU
> - I/O 操作本身不怎么耗 CPU

> 注意：
> 
> “内存泄露” 可能是真实泄漏点，也可能是堆内存占用过大、内存吃紧，间接导致 ANR/CPU 过高。

## 4. ANR 类型及日志关键字

表格

|ANR 类型|超时时间|Logcat 关键字|
|---|---|---|
|InputDispatching Timeout|5s|`Input event dispatching timed out`|
|BroadcastTimeout|前台 10s<br><br>后台 60s|`Timeout of broadcast BroadcastRecord`|
|ServiceTimeout|前台 20s<br><br>后台 200s|`Timeout executing service`|
|ContentProviderTimeout|10s|`timeout publishing content providers`|

## 5. ANR 定位方法

入手点：ANR 前后日志 + `/data/anr/traces.txt`

### 5.1 日志分析

1. 搜索 `ANR in`：定位发生 ANR 的进程
2. 搜索 `ActivityManager:CPU usage from`：判断是否 CPU 过高

### 5.2 traces.txt 分析

1. 搜索 `held by tid=`：排查死锁
2. 查看 `stackSize=`：判断是否内存问题

### 5.3 整体分析步骤

1. 确定 ANR 时间点
    
    - 关键字：`anr in`、`blocked`、`blockMonitor`、`freezedector`
    - 获取：版本号、PID、是否前台、页面、温度、频点、ANR 类型
    
2. 根据 ANR 类型回溯对应时间段日志
    
    - 查找 `Subject` / `Reason`
    
3. 分析 ANR 堆栈
    
    - 查找 `sysTid=线程号`
    - 状态为 `block`/`timeout` 一般为真实问题堆栈
    

### 5.4 核心分析思路

1. **查看 CPU 负载**
    
    - user：用户态
    - kernel：内核态
    - iowait：IO 等待
    - faults：内存缺页
    
2. **查看主线程状态**
    
    - `Native`：正常空闲，等待消息
    - `Runnable`：主线程执行耗时操作
    - `Blocked`：主线程被锁阻塞，可查 `waiting to lock...held by thread`
    
3. **其他应用抢占 CPU**
    
    日志会显示高占比包名，CPU 上限 = 核心数 × 100%
4. **系统服务 / Binder 问题**
    
    搜索：`BinderProxy.transactNative`
    
    可能原因：Binder 超时、Binder 资源耗尽
5. **内存紧张导致 ANR**
    
    - 查看 ANR 前空闲内存
        
        - 4G 及以下：阈值约 350M
        - 4G 以上：阈值约 450M
        
    - 查看 `trimMemory` 调用（level 越大内存越紧张：5/10/20/40/60/80）
    

## 6. 典型示例

1. 主线程与子线程互锁导致 ANR
2. Android 系统库崩溃（如 `libweexcore.so` 等）
3. `nativePollOnce` 阻塞
4. Binder 对端阻塞（如第三方推送 SDK）

## 7. 非应用自身导致的 ANR

1. **热限频**
    
    - 温度 > 41℃
    - 大核频点 < 1.8GHz 且跑满
    
2. **Monkey 异常场景**
    
    - 焦点不在当前应用 / 页面已销毁，仍分发输入事件
    - 不属于 App 代码问题
    

## 8. ANR 根本原因分类总结

表格

|原因类别|具体表现|
|---|---|
|主线程自身问题|主线程执行耗时操作、死循环、复杂计算、同步 IO / 网络|
|线程间竞争|主线程等待子线程锁、死锁、子线程崩溃导致主线程无限等待|
|CPU 被抢占|其他进程占满 CPU、频繁 GC|
|系统资源瓶颈|内存紧张、GC 频繁、系统服务繁忙、Binder 耗尽|
|系统 / 环境问题|热限频、Monkey 异常、系统服务超时|