ANR原因分析及解决方法
(技术文档)
1
内容目录
1 ANR是如何产生的 ............................................................................................................................ 5 1.1 ANR产生条件 ..................................................................................................................... 5 1.2 引起ANR的根本原因 ............................................................................................................ 5 2 ANR原因分析方法 ............................................................................................................................ 5 2.1 通过logcat日志分析原因 ....................................................................................................... 5 2.2 通过trace文件分析原因 ......................................................................................................... 9 3 ANR解决方法 ................................................................................................................................ 12 4 参考资料 ......................................................................................................................................... 12
2
1 1.1
ANR是如何产生的 ANR产生条件
ANR的产生需要同时满足三个条件:
? 主线程:只有应用程序进程的主线程响应超时才会产生ANR;
? 超时时间:产生ANR的上下文不同,超时时间也不同,但只要超过这个时间上限没有响应就会产生
ANR;
? 输入事件/特定操作:输入事件是指按键、触屏等设备输入事件,特定操作是指BroadcastReceiver和
Service的生命周期中的各个函数调用。
产生ANR的上下文不同,导致ANR原因也不同,主要有以下三种情况:
? 应用进程的主线程对输入事件在5s内没有处理完毕;
? 应用进程的主线程在执行BroadcastRecevier的onReceive函数时10s内没有处理完毕; ? 应用进程的主线程在执行Service的各个生命周期函数时20s内没有处理完毕;
1.2 引起ANR的根本原因
引起ANR的根本原因,总的来说可以归纳为两类:
? ?
应用进程自身引起的,比如:主线程阻塞、挂起、死循环,执行耗时操作等;
其他进程引起的,比如:其他进程CPU占用率过高,导致当前应用进程无法抢占到CPU时间片。常见的问题如文件读写频繁,io进程CPU占用率过高,导致当前应用出现ANR;
2
2.1
ANR原因分析方法
通过logcat日志分析原因
举一个开发过程中的ANR实例,《从云盘上下载视频到本地,进入下载中心删除任务和文件,进入文件管理提示‘文件管理无响应’》,在logcat日志中输出了以下ANR信息:
01-21 23:58:40.265 975 991 E ActivityManager: ANR in com.letv.filemanager
01-21 23:58:40.265 975 991 E ActivityManager: Reason: Executing service com.letv.filemanager/.netstorage.service.DlnaService 01-21 23:58:40.265 975 991 E ActivityManager: Load: 5.62 / 4.3 / 3.55
01-21 23:58:40.265 975 991 E ActivityManager: CPU usage from 30331ms to 0ms ago:
01-21 23:58:40.265 975 991 E ActivityManager: 26% 1760/com.letv.airplay: 24% user + 1.6% kernel / faults: 1094 minor 01-21 23:58:40.265 975 991 E ActivityManager: 15% 787/cdnclient: 0% user + 15% kernel 01-21 23:58:40.265 975 991 E ActivityManager: 13% 298/kswapd0: 0% user + 13% kernel
01-21 23:58:40.265 975 991 E ActivityManager: 9.5% 1437/com.letv.dmr: 9% user + 0.5% kernel / faults: 572 minor 01-21 23:58:40.265 975 991 E ActivityManager: 9.1% 953/flush-179:0: 0% user + 9.1% kernel 01-21 23:58:40.265 975 991 E ActivityManager: 5.8% 788/collector: 0.8% user + 4.9% kernel 01-21 23:58:40.265 975 991 E ActivityManager: 5% 419/mmcqd: 0% user + 5% kernel
01-21 23:58:40.265 975 991 E ActivityManager: 2.9% 814/ld-linux.so.3: 1.1% user + 1.8% kernel 01-21 23:58:40.265 975 991 E ActivityManager: 2.5% 822/dd: 0.2% user + 2.2% kernel
01-21 23:58:40.265 975 991 E ActivityManager: 1.4% 2533/com.letv.threeScreen: 0.7% user + 0.7% kernel / faults: 134 minor 01-21 23:58:40.265 975 991 E ActivityManager: 0.5% 817/logcat: 0% user + 0.4% kernel 01-21 23:58:40.265 975 991 E ActivityManager: 0.4% 7/events/0: 0% user + 0.4% kernel
01-21 23:58:40.265 975 991 E ActivityManager: 0.4% 1254/com.letv.t2.launcher: 0.4% user + 0% kernel / faults: 20 minor 01-21 23:58:40.265 975 991 E ActivityManager: 0.2% 975/system_server: 0% user + 0.1% kernel / faults: 34 minor 1 major 01-21 23:58:40.265 975 991 E ActivityManager: 0.2% 1452/com.letv.downloads: 0.1% user + 0.1% kernel / faults: 40 minor 01-21 23:58:40.265 975 991 E ActivityManager: 0.1% 808/virtualkeypad: 0% user + 0.1% kernel 01-21 23:58:40.265 975 991 E ActivityManager: 0.1% 1292/RTW_CMD_THREAD: 0% user + 0.1% kernel 01-21 23:58:40.265 975 991 E ActivityManager: 0% 753/jbd2/mmcblk9-8: 0% user + 0% kernel 01-21 23:58:40.265 975 991 E ActivityManager: 0% 8/events/1: 0% user + 0% kernel
3
01-21 23:58:40.265 975 991 E ActivityManager: 0% 177/bdi-default: 0% user + 0% kernel 01-21 23:58:40.265 975 991 E ActivityManager: 0% 786/letvmanager: 0% user + 0% kernel
01-21 23:58:40.265 975 991 E ActivityManager: 0% 1472/com.letv.filemanager: 0% user + 0% kernel
01-21 23:58:40.265 975 991 E ActivityManager: 0% 1737/com.letv.medialog: 0% user + 0% kernel / faults: 48 minor 01-21 23:58:40.265 975 991 E ActivityManager: 62% TOTAL: 7.2% user + 10% kernel + 43% iowait + 1% softirq 01-21 23:58:40.265 975 991 E ActivityManager: CPU usage from 3195ms to 3733ms later:
01-21 23:58:40.265 975 991 E ActivityManager: 15% 975/system_server: 3.7% user + 11% kernel / faults: 1 minor 01-21 23:58:40.265 975 991 E ActivityManager: 15% 991/ActivityManager: 3.7% user + 11% kernel 01-21 23:58:40.265 975 991 E ActivityManager: 7.5% 1760/com.letv.airplay: 7.5% user + 0% kernel 01-21 23:58:40.265 975 991 E ActivityManager: 5.6% 2615/SocketListener(: 5.6% user + 0% kernel 01-21 23:58:40.265 975 991 E ActivityManager: 5.5% 419/mmcqd: 0% user + 5.5% kernel 01-21 23:58:40.265 975 991 E ActivityManager: 3.7% 298/kswapd0: 0% user + 3.7% kernel 01-21 23:58:40.265 975 991 E ActivityManager: 3.7% 788/collector: 0% user + 3.7% kernel 01-21 23:58:40.265 975 991 E ActivityManager: 3.7% 866/collector: 0% user + 3.7% kernel 01-21 23:58:40.265 975 991 E ActivityManager: 1.8% 865/collector: 0% user + 1.8% kernel 01-21 23:58:40.265 975 991 E ActivityManager: 3.7% 814/ld-linux.so.3: 1.8% user + 1.8% kernel 01-21 23:58:40.265 975 991 E ActivityManager: 1.8% 1009/814Linux hotplu: 1.8% user + 0% kernel 01-21 23:58:40.265 975 991 E ActivityManager: 1.8% 1013/IRQThread_157: 0% user + 1.8% kernel
01-21 23:58:40.265 975 991 E ActivityManager: 0.3% 1254/com.letv.t2.launcher: 0.3% user + 0% kernel / faults: 1 minor 01-21 23:58:40.265 975 991 E ActivityManager: 0.3% 1254/etv.t2.launcher: 0.3% user + 0% kernel 01-21 23:58:40.265 975 991 E ActivityManager: 54% TOTAL: 2.9% user + 5.9% kernel + 45% iowait
我们可以通过ActivityManagerService的appNotResponding方法看一下ANR信息是如何记录到logcat日志中的:
.\\framework\\base\\services\\java\\com\\android\\server\\am\\ActivityManagerService.java
final void appNotResponding(ProcessRecord app, ActivityRecord activity,
ActivityRecord parent, boolean aboveSystem, final String annotation) { ......
synchronized (this) {
// PowerManager.reboot() can block for a long time, so ignore ANRs while shutting
down.
if (mShuttingDown) { //重启时忽略ANR
Slog.i(TAG, \ return;
} else if (app.notResponding) { //之前已处理过则不再处理
Slog.i(TAG, \ return;
} else if (app.crashing) {
//已经Crash的进程则不再处理ANR
Slog.i(TAG, \ return; }
//设置ANR标志,用于防止重复处理
// In case we come through here for the same app before completing // this one, mark as anring now so we will bail out. app.notResponding = true;
// Log the ANR to the event log.
EventLog.writeEvent(EventLogTags.AM_ANR, app.userId, app.pid, app.processName, app.info.flags, annotation);
//将发生ANR的应用pid放入firstPids集合中
4
相关推荐: