其他
Android ANR/Crash Log日志分析技巧总结(建议收藏)
推荐阅读
系统定制编译之Android.mk和Android.bp详解
Android高级开发中ANR/Native Crash问题的解决方法
干货|Android系统中run-as和su命令的源码解析(升降权限)
Android系统定制/测试(Crash/ANR等Bug/性能分析必备技巧)
Android系统定制之Android.mk和Android.bp语法详解(精通版)
ANR日志Trace文件获取
系统生成的Trace文件保存在data/anr
adb pull data/anr/
traces.txt只保留最后一次ANR的信息
Android系统有个DropBox功能功能,它能记录系统出现的crash错误,因此保留有发生过的ANR的信息
/data/system/dropbox
获取系统Crash Log
adb shell dumpsys dropbox --print >>log.txt
导致ANR的常见几种情况
1.Input dispatching timed out(5 seconds)按键或触摸事件处理超时(一般是UI主线程做了耗时的操作,这类ANR最常见)
2.BroadcastTimeout(10 seconds)广播的分发和处理超时(一般是onReceiver执行时间过长)
3.ServiceTimeout(20 seconds)Service的启动和执行超时
另外还有ProviderTimeout和WatchDog等导致的ANR.还有当系统内存或CPU资源不足时容易出现ANR,一般这种情况会有lowmemorykill的log打印
应用ANR产生的时候,ActivityManagerService的appNotResponding方法就会被调用,然后在/data/anr/traces.txt文件中写入ANR相关信息
final void appNotResponding(ProcessRecord app, ActivityRecord activity,
ActivityRecord parent, boolean aboveSystem, final String annotation) {
// ... ...
if (MONITOR_CPU_USAGE) {
updateCpuStatsNow(); // 更新CPU使用率
}
// ... ...
final ProcessCpuTracker processCpuTracker = new ProcessCpuTracker(true);
// dumpStackTraces是输出traces文件的函数
File tracesFile = dumpStackTraces(true, firstPids, processCpuTracker, lastPids,
NATIVE_STACKS_OF_INTEREST);
String cpuInfo = null;
if (MONITOR_CPU_USAGE) {
updateCpuStatsNow(); // 再次更新CPU信息
synchronized (mProcessCpuTracker) {
// 输出ANR发生前一段时间内的CPU使用率
cpuInfo = mProcessCpuTracker.printCurrentState(anrTime);
}
info.append(processCpuTracker.printCurrentLoad());
info.append(cpuInfo);
}
// 输出ANR发生后一段时间内的CPU使用率
info.append(processCpuTracker.printCurrentState(anrTime));
Slog.e(TAG, info.toString());
if (tracesFile == null) {
// There is no trace file, so dump (only) the alleged culprit's threads to the log
Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
}
// 将ANR信息同时输出到DropBox中
addErrorToDropBox("anr", app, app.processName, activity, parent, annotation,
cpuInfo, tracesFile, null);
// ... ...
synchronized (this) {
// 显示ANR提示对话框
// Bring up the infamous App Not Responding dialog
Message msg = Message.obtain();
HashMap<String, Object> map = new HashMap<String, Object>();
msg.what = SHOW_NOT_RESPONDING_MSG;
msg.obj = map;
msg.arg1 = aboveSystem ? 1 : 0;
map.put("app", app);
if (activity != null) {
map.put("activity", activity);
}
mUiHandler.sendMessage(msg);
}
}