赞
踩
ANR(Application Not Responding),即应用程序无响应,Android 系统指定某些事件需要在规定时间内完成,如果超过预定时间还能未能得到有效响应,就会造成 ANR。具体表现为,应用位于前台时,系统会向用户显示一个对话框,如下图所示。用户可以选择“wait”让程序继续运行,也可以选择“Close app”强制关闭。
系统发生 ANR 时会在 system_server 进程调用 AppNotRespondingDialog.show() 方法,弹出对话框提示用户,对话框的调用链如下:
ProcessRecord.appNotResponding()
└── mService.mUiHandler.sendMessage(SHOW_NOT_RESPONDING_UI_MSG)
└── AMS.UiHandler.handleMessage()
└── AppErrors.handleShowAnrUi()
└── AppNotRespondingDialog.show()
其中 AppErrors.appNotResponding() 方法是弹出 ANR 对话框的唯一入口,查看其调用关系如如下图:
总结有以下 4 种场景的超时会引起 ANR:
以下是 Android 原生系统对不同类型的超时阈值设置,各手机厂商或芯片厂商也会对此值进行自行定制。
类型 | TimeOut (sec) |
---|---|
Service | 前台:20,后台:200 |
Broadcast | 前台:10,后台:60 |
ContentProvider | 10 |
InputDispatching | 5 |
触发 ANR 的过程大致可分为三个步骤: 埋下炸弹 ->执行任务 ->引爆炸弹(或拆除炸弹)
其主体实现在系统层:
在第 3 步中,如果任务在规定时间内执行完成,通知 system_server 进程移除监控,则炸弹被拆除,不会发生 ANR 异常。
以 Service 超时为例,从源码来分析其超时机制引发 ANR 的流程。
Service Timeout 是位于 system_server 进程 -> ActivityManager 线程中 AMS.MainHandler 收到 SERVICE_TIMEOUT_MSG
消息时触发。
对于 Service 有两类:
Service ANR检测
Android 是通过设置定时消息实现的检测 Service 超时的。定时消息是由 AMS 的消息队列处理的(system_server 的 ActivityManager 线程)。AMS 有 Service 运行的上下文信息。
Service ANR 主体实现在 ActiveServices 中。 当 Service 的生命周期开始时,bumpServiceExecutingLocked() 会被调用,紧接着会调用 scheduleServiceTimeoutLocked()
frameworks/base/services/core/java/com/android/server/am/ActiveServices.java
void scheduleServiceTimeoutLocked(ProcessRecord proc) {
if (proc.executingServices.size() == 0 || proc.thread == null) {
return;
}
Message msg = mAm.mHandler.obtainMessage(
ActivityManagerService.SERVICE_TIMEOUT_MSG);
msg.obj = proc;
mAm.mHandler.sendMessageDelayed(msg,
proc.execServicesFg ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT);
}
当 Service 的生命周期结束时,会调用 serviceDoneExecutingLocked() 方法,之前抛出的 SERVICE_TIMEOUT_MSG
消息在这个方法中会被清除。 如果在超时时间内,SERVICE_TIMEOUT_MSG
没有被清除,那么,AMS.MainHandler 就会响应这个消息
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
case SERVICE_TIMEOUT_MSG: {
mServices.serviceTimeout((ProcessRecord)msg.obj);
} break;
serviceTimeout 在 ActiveServices 启动打印信息
frameworks/base/services/core/java/com/android/server/am/ActiveServicesjava
if (timeout != null && mAm.mProcessList.mLruProcesses.contains(proc)) { Slog.w(TAG, "Timeout executing service: " + timeout); StringWriter sw = new StringWriter(); PrintWriter pw = new FastPrintWriter(sw, false, 1024); pw.println(timeout); timeout.dump(pw, " "); pw.close(); mLastAnrDump = sw.toString(); mAm.mHandler.removeCallbacks(mLastAnrDumpClearer); mAm.mHandler.postDelayed(mLastAnrDumpClearer, LAST_ANR_LIFETIME_DURATION_MSECS); anrMessage = "executing service " + timeout.shortInstanceName; } // 打印 ANR 信息 if (anrMessage != null) { mAm.mAnrHelper.appNotResponding(proc, anrMessage); }
通过 ANRHelper 打印 ANR 信息
frameworks/base/services/core/java/com/androidserver/am/AnrHelper.java
void appNotResponding(ProcessRecord anrProcess, String activityShortComponentName,
ApplicationInfo aInfo, String parentShortComponentName,
WindowProcessController parentProcess, boolean aboveSystem, String annotation) {
synchronized (mAnrRecords) {
mAnrRecords.add(new AnrRecord(anrProcess, activityShortComponentName, aInfo,
parentShortComponentName, parentProcess, aboveSystem, annotation));
}
startAnrConsumerIfNeeded();
}
Service 的 ANR 机制总结
通过定时消息跟踪 Service 的运行,当定时消息被响应时,说明 Service 还没有运行完成,这就意味着 Service ANR。
ANR 问题主要有两种原因:应用自身的问题 和 系统异常导致的问题。在分析 ANR 问题的时候,最主要的就是要确定是哪个原因导致的
ANR 问题一般的分析步骤如下:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。