ANR场景分析识别(以xcrash日志为例)

31 阅读2分钟

ANR分析通用流程

┌──────────────────────────────────────────────────────┐
│            ANR日志分析标准流程                         │
└──────────────────────────────────────────────────────┘

第1步: 查看基本信息
   ├─ 应用包名、版本
   ├─ 设备型号、系统版本
   ├─ 发生时间
   └─ 进程ID

第2步: 定位主线程堆栈
   ├─ 搜索 "main" tid=1
   ├─ 查看线程状态 (Blocked/Native/Runnable)
   ├─ 分析堆栈顶部方法
   └─ 查找锁信息 (waiting to lock / held by)

第3步: 分析相关线程
   ├─ 根据 "held by thread X" 查找持有锁的线程
   ├─ 查看该线程的状态和堆栈
   ├─ 分析该线程在做什么操作
   └─ 确认是否存在阻塞调用

第4步: 确定问题类型
   ├─ 死锁:多个线程互相等待
   ├─ 主线程耗时:复杂计算、IO操作
   ├─ 锁竞争:大量线程争抢同一个锁
   └─ 系统资源:CPU、内存、磁盘IO

第5步: 定位根本原因
   ├─ 绘制线程关系图
   ├─ 分析时间序列
   ├─ 找出触发条件
   └─ 确定问题代码位置

第6步: 提出解决方案
   ├─ 短期:规避或缓解
   ├─ 长期:重构或优化
   └─ 验证:测试和监控

第7步: 预防措施
   ├─ 代码审查规范
   ├─ 静态分析工具
   ├─ 性能监控
   └─ 用户反馈收集

场景1:主线程执行耗时操作

特征

"main" prio=5 tid=1 Runnable
  at com.example.MainActivity.processData(MainActivity.java:100)
  at com.example.MainActivity.onCreate(MainActivity.java:50)

原因:主线程直接执行CPU密集或IO操作
解决:移到后台线程

场景2:死锁

特征

"main" tid=1 Blocked
  - waiting to lock <0x12345678> held by thread 5

"WorkerThread" tid=5 Blocked
  - waiting to lock <0x87654321> held by thread 1

原因:循环等待锁
解决:统一加锁顺序或使用tryLock

场景3:锁竞争激烈

特征

"main" tid=1 Blocked
  - waiting to lock <0x12345678> held by thread 5

"Thread-5" tid=5 Blocked
  - waiting to lock <0x12345678> held by thread 10

... 大量线程等待同一个锁

原因:锁粒度太粗
解决:细化锁或使用无锁数据结构

场景4:Binder调用超时

特征

"main" tid=1 Native
  at android.os.BinderProxy.transactNative(Native method)
  at android.os.BinderProxy.transact(Binder.java:xxx)
  at android.app.IActivityManager$Stub$Proxy.xxx

原因:跨进程调用耗时或对方无响应
解决:异步调用或优化服务端

场景5:消息队列堵塞

特征

大量消息积压在MessageQueue中
Handler处理消息过慢

原因:Handler消息处理耗时
解决:优化消息处理逻辑


实用工具和命令

分析工具

  1. Android Studio Profiler

    • CPU Profiler:查看方法耗时
    • Memory Profiler:检查内存泄漏
  2. Systrace

    python systrace.py -t 10 -o trace.html \
      sched freq idle am wm gfx view binder_driver hal dalvik
    
  3. 命令行分析

    # 快速查看主线程
    grep -A 50 '"main".*tid=1' anr.txt
    
    # 查找所有Blocked线程
    grep -B 2 'Blocked' anr.txt
    
    # 统计线程状态
    grep 'prio=' anr.txt | awk '{print $NF}' | sort | uniq -c
    

监控方案

// 1. ANR-WatchDog
implementation 'com.github.anrwatchdog:anrwatchdog:1.4.0'

new ANRWatchDog().setANRListener(error -> {
    // 上报ANR
}).start();

// 2. BlockCanary
implementation 'com.github.markzhai:blockcanary-android:1.5.0'

// 3. Matrix (微信开源)
implementation 'com.tencent.matrix:matrix-android-lib:2.0.0'

学习资源

  1. 官方文档

  2. 推荐阅读

    • 《Android性能优化最佳实践》
    • 《深入理解Android内核设计思想》
  3. 开源工具