目录
原理
主要分析流程
参考连接
-
ANR 问题主要有两种原因:应用自身的问题 和 系统异常导致的问题。在分析 ANR 问题的时候,最主要的就是要确定是哪个原因导致的
ANR 问题一般的分析步骤如下:
- 分析 trace.txt:查看是否有明显的异常,比如死锁、SystemServer 异常持锁等
- 死锁堆栈: 观察 Trace 堆栈,确认是否有明显问题,如主线程是否与其他线程发生死锁,如果是进程内部发生了死锁,只需找到与当前线程死锁的线程,问题即可解决
- 业务堆栈: 观察 Trace 堆栈,发现当前主线程堆栈正在执行业务逻辑,这时候需要分析对应的代码,查看是否真的有问题
- 重要:如果业务方觉得这里没有问题,需要进一步分析,因为 Trace 堆栈可能并不是真正耗时的地方,需要结合其他信息一起分析
- IPC Block 堆栈: 观察通过 Trace 堆栈,发现主线程堆栈是在跨进程(Binder)通信,这时候可以根据其他 Log、Binder Info 等信息,来分析 IPC 信息
- 大部分 IPC 都是在跟 SystemServer,如果没有 BinderInfo,可以搜索对应的接口关键字,在 SystemServer 进程查找是否有相关的堆栈
- 重要:如果业务方觉得这里没有问题,需要进一步分析,因为 Trace 堆栈可能并不是真正耗时的地方,需要结合其他信息一起分析
- 系统堆栈: 通过观察 Trace,发现当前堆栈只是简单的系统堆栈,比如 NativePollOnce,想要搞清楚是否发生严重耗时,以及进一步的分析定位
- 重要:大部分比较难分析的 ANR 基本上应用主线程堆栈都是 NativePollOnce 这个状态,之所以出现这种状态,可能有下面几个原因
- 确实没有消息在处理,可能进程被冻结,或者 No Focused Window 这种 ANR
- 刚好处理完某一个耗时消息,系统抓堆栈的时候,已经晚了,耗时的状态没有抓到
- 线程调度的原因,主线程没有机会执行
- 重要:大部分比较难分析的 ANR 基本上应用主线程堆栈都是 NativePollOnce 这个状态,之所以出现这种状态,可能有下面几个原因
- 分析 Event Log:看具体的 ANR 时间(搜索 am_anr),看看是否跟 ANR log 能够对上,以确定 ANR Log 是否有效,如果 ANR Log 有效,分析 ANR Log,提取有用信息:pid、tid、死锁等,遇到 ANR 问题,摆在我们面前的 trace 是不是第一案发现场,如果 ANR 发生的输出的信息很多,当时的 CPU 和 I/O 资源比较紧张,那么这段日志输出的时间点可能会延迟 10 秒到 20 秒都有可能,所以我们有时候需要提高警惕。不过正常情况下,EventLog 中的 am_anr 的输出时间是最早的,也是最接近 ANR 时间的 (提取有效信息到单独文件中)
- 分析 Android Log:看 MainLog(Android Log) 或者 SystemLog 查看 ANR 详细信息(搜索 ANR in),提取有效的信息 (提取有效信息到单独文件中)
- 发生 ANR 的时间
- 打印 ANR 日志的进程
- 发生 ANR 的进程
- 发生 ANR 的原因
- CPU 负载
- Memory 负载
- CPU 使用统计时间段
- 各进程的 CPU 使用率
- 总的 CPU 使用率
- 缺页次数 fault
- xxx minor 表示高速缓存中的缺页次数,可以理解为进程在做内存访问
- xxx major 表示内存的缺页次数,可以理解为进程在做 IO 操作
- CPU 使用汇总
- 配合 Main Log(Android Log) 和 EventLog 把 CPU 开始和结束的时间点内的所有有用信息提取出来到一个 文件中,搜索的主要关键字:pid,进程名,WindowManager、ActivityManager(关键字参考下一节的关键 Log 那里)
- 收集关键操作场景,比如解锁、安装应用、亮灭屏、应用启动等
- 收集异常和系统关键 Log
- 系统变慢 :比如 Slow operation、Slow dispatch、Slow delivery、dvm_lock_sample、binder_sample
- 进程变化 :am_kill、am_proc_died、lowmemorykiller、ANR、应用启动关系等
- 系统信息 :cpu info、meminfo、binder info(是否满了) 、iowait (是否过高)
- 消息监控:ANR 前的 ANR Message 打印,Block Message 信息,应用自己代码执行逻辑推断出的 Message 耗时等
- 收集 ANR 进程的所有关键线程的运行情况、线程优先级等
- 根据第四步提取出来的关键信息文件,进一步理出系统当时的情况、状态(推荐 vscode 或者 notepad ++ ,有 线索就全局搜索)),比如
- 是处于低内存频繁杀进程?
- 重启第一次解锁系统繁忙
- 还是短时间内多个应用启动系统繁忙
- 还是应用自己的逻辑等待?
- 针对不同的 ANR 类型,提取不同的信息
- 不行就加 Log 复现
案例分析
Android 卡顿与ANR的分析实践 中 CPU占用分析值得一看。