Android ANR 学习与总结
1、三种ANR
1) Key/Touch Input Dispatch Timeout 安卓默认5秒 log示例:Input dispatching timed out;
2) Broadcast TimeOut 安卓默认10秒 log示例:Timeout of broadcast;
3) Service TimeOut 安卓默认20秒 log示例:Timeout executing service;
2、主线程
每个Java process都有一个main Thread和一个main message queue(main thread == activity thread),在主线程进行UI相关的操作,比如draw和监听UI events。main thread从main message queue取出message尽快进行处理,处理完当前的消息后才能进行下一个message的处理。如果main thread卡在执行某个message时就会造成ANR,普通Service也是在main thread中运行,从而也会造成ANR(这时可以考虑使用IntentService)。
3、log文件
/data/anr/traces.txt以及mtk的aee_exp 中db文件和mobilelog中 AP log。
通过log需要得到:
1) ANR发生时间点;
2) 发生ANR的进程号;
3) ANR的类型;
4) ANR发生前进程的相关信息。
MoblileLog:
Events log (搜anr):
其中am_anr内容中对应各项为:
am_anr (User|1|5),(pid|1|5),(Package Name|3),(Flags|1|5),(reason|3)
可以得知发生anr的进程号为10828,进程名为com.xie.mytest,以及发生原因。
Main log(搜Application is not responding):
可以得到具体发生anr的activity:com.xie.mytest.MainActivity。
再看events log:
可以看到anr进程发生anr前在做的一些事情。
Traces.txt 同样可得到发生anr的进程号等信息:
4. anr分析
1)发生anr前是否发生了NE/JE异常,如果有,先解决异常;
2)trace文件是否有效;
3)通过event log发生时间点定位到main log;
4)在trace.txt文件中找到anr进程调用栈。
Trace文件分析:
a. 找到anr进程的主线程查看是否有卡住,如果没有就要检查进程的子线程、main log、event log以及kernel log,看看有没有有用的信息;
b. Anr进程主线程卡住:
可以看到主线程处于sleep状态导致anr。一般来说DALVIK THREADS下面有一段比较长的log,一般是这个进程主线程卡住了,如下图所示,而其他的进程一般处于idle状态。
c. 其他进程的idle(空闲、就绪)状态分析:
可以看到这个进程的主线程在等待下一条message进行处理,因此是idle状态而不是卡住。
d. Cpu状态分析:
通过ActivityManager打出的CPU usage可以知道anr发生前一段时间和发生后一段时间cpu的使用情况
IO堵塞:
根据38% TOTAL: 18% user + 16% kernel + 1.1% iowait + 2.4% softirq,如果iowait的使用量很高,就说明可能是IO堵塞导致cpu忙从而出现anr。这时应该是出现anr的线程进行了文件操作,需要去检查这个操作。
事件等待:
a. 等待锁wait lock、VMWait
可以看到子线程tid=17持有锁,所以要查看这个线程当前在进行什么操作,为什么没有释放。
b. 等待binder的返回(binder transact)
getUuids()在等binder返回,下图为Service端getUuids()在执行的一些操作,这就需要对应负责人去进行分析。
Binder未返回有可能是在主线程中大量进行query DB,如下图,这时候cpu usage可能并不高: