ANR 的分析方法和关键日志

508 阅读4分钟

这篇文章是 Android ANR 系列的第二篇,主要介绍了 ANR 的分析方法和关键日志,旨在帮助开发者掌握 ANR 问题的排查技巧。以下是详细总结:

一、ANR 分析基本流程

  1. 确定 ANR 日志有效性

    • 通过 EventLog 搜索 “am_anr”,确认 ANR 发生时间与日志时间是否一致,避免因系统资源紧张导致日志延迟。
  2. 提取关键信息

    • 从 MainLog 或 SystemLog 中获取 ANR 进程名、PID、触发原因(如输入事件超时、服务启动超时等)、CPU 和内存负载等。
  3. 收集系统状态

    • 包括 CPU 使用率、内存压力、IO 负载、进程调度信息等,可通过adb bugreport获取完整日志。
  4. 区分应用与系统问题

    • 分析应用是否存在主线程耗时操作、死锁、Binder 调用延迟等;同时检查系统资源(如 CPU 负载、内存不足、IO 瓶颈)是否异常。

二、ANR 日志核心内容解析

  1. 线程状态与堆栈

    • 线程状态:如 “state=S” 表示睡眠,“Blocked” 表示阻塞,可通过traces.txt查看线程堆栈,识别主线程阻塞位置(如等待锁、IO 操作)。
    • 正常 vs 异常堆栈:正常主线程常处于 “nativePollOnce” 等待消息状态,异常堆栈会显示具体阻塞方法(如DiskStorageCache.e())。
  2. CPU 使用率分析

    • 负载指标:通过 “Load: 15.29 / 5.19 / 1.87” 判断系统负荷(1 分钟、5 分钟、15 分钟平均负载),超过 0.7 需警惕,超过 1.0 需立即优化。
    • 进程 CPU 占比:如 “30% 5991/com.xxx.launcher” 表示应用用户态和内核态 CPU 占用率,结合 “faults” 判断 IO 操作频率(major fault 为磁盘 IO)。
  3. 内存与 IO 负载

    • 内存压力:从/proc/pressure/memory获取 “some” 和 “full” 阻塞时间占比,“full” 过高(如超过 10%)表明系统资源竞争严重。
    • IO 负载:通过 “major faults” 数量判断磁盘 IO 频率,大量 major fault 可能导致主线程阻塞。

三、系统关键日志与异常场景

  1. ANR 相关系统日志

    • Slow operation:AMS 任务耗时超过 50ms,如 “Slow operation: 138ms so far”,提示系统卡顿。
    • Looper Slow dispatch/delivery:消息分发或处理超时,如 “Slow dispatch took 418ms”,表明主线程消息队列阻塞。
    • dvm_lock_sample:线程等待锁超时(如 1500ms),显示持锁线程和阻塞位置。
    • binder_sample:Binder 跨进程调用耗时超过阈值(如 2010ms),可通过接口 Code 定位具体方法。
  2. 进程异常与杀进程日志

    • am_kill:记录进程被杀原因,如 “remove task”“anr”“crash” 等,区分主动杀进程(如用户强制停止)和被动杀进程(如 ANR、OOM)。
    • lowmemorykiller:内核日志中记录因内存不足杀进程,如 “Kill 'com.heytap.themestore' to free 105068kB”。
    • am_proc_died:进程异常死亡,需结合堆栈分析崩溃原因。
  3. 应用冻结与调度异常

    • 应用冻结:日志如 “xxxHansManager : freeze uid”,因功耗优化导致应用暂停,可能触发 ANR。
    • D 状态进程:进程处于不可中断睡眠状态,如 “__refrigerator” 调用,需检查内核调度或功耗策略。

四、典型场景日志分析

  1. 灭屏与亮屏

    • 关键日志:power_screen_statescreen_toggled,灭屏时screen_toggled=0,亮屏时=1,结合power_screen_broadcast_done时间判断耗时。
  2. 解锁与应用启动

    • 解锁流程:通过wm_set_keyguard_shown日志跟踪 Keyguard 状态变化,如从锁屏到桌面的焦点转移。
    • 应用启动:记录wm_create_activityam_proc_start等事件,计算启动耗时(如wm_activity_launch_time: 471ms)。
  3. 窗口焦点变化

    • 焦点转移日志:如 “Changing focus from Launcher to App”,异常时可能触发 “No Focused Window ANR”。

五、ANR 治理方法论

  1. 被动分析

    • 堆栈对比:比较 ANR 前后堆栈变化,识别线程状态迁移(如从 Runnable 到 Blocked)。
    • 动态追踪:使用systracePerfetto监控主线程消息处理周期,定位耗时操作(如 SharedPreferences 写入)。
  2. 主动防御

    • 架构优化:限制跨进程调用层级,为业务模块分配 Binder 事务配额,强化异步边界(如 HandlerThread)。
    • 机器学习预测:通过 CPU 调度、内存回收等指标建模,提前识别 ANR 风险(如 Google Android Vitals 技术)。

六、参考资料与工具

  • 日志抓取adb bugreport获取系统全量日志,traces.txt存储 ANR 线程堆栈。
  • 性能工具:Android Studio CPU Profiler、Systrace、Perfetto。
  • 案例参考:西瓜视频、今日头条、高爷 ANR 优化实践系列文章,以及 Gityuan 等技术博客。

通过上述方法,开发者可从日志中提取关键信息,逐步定位 ANR 根因,结合系统设计与应用代码优化,提升应用响应性能。