1 2 3 ANR in com.autonavi.minimap PID: 28415 Reason: executing service com.autonavi.minimap/com.alipay.mobile.common.logging.process.LogServiceInPushProcess
此问题发生在Service中超时,抛出异常的时机是在系统进程
Service启动 会使用Handler发送一个延时的消息
1 2 3 4 5 6 7 8 9 10 void scheduleServiceTimeoutLocked (ProcessRecord proc) { if (proc.mServices.numberOfExecutingServices() == 0 || proc.getThread() == null ) { return ; } Message msg = mAm.mHandler.obtainMessage( ActivityManagerService.SERVICE_TIMEOUT_MSG); msg.obj = proc; mAm.mHandler.sendMessageDelayed(msg, proc.mServices.shouldExecServicesFg() ? SERVICE_TIMEOUT : SERVICE_BACKGROUND_TIMEOUT); }
如果在timeout时间范围内没有移除此消息,将会触发ANR异常
1 2 3 case SERVICE_TIMEOUT_MSG: { mServices.serviceTimeout((ProcessRecord) msg.obj); } break ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 void serviceTimeout (ProcessRecord proc) { String anrMessage = null ; synchronized (mAm) { if (timeout != null && mAm.mProcessList.isInLruListLOSP(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; } else { Message msg = mAm.mHandler.obtainMessage( ActivityManagerService.SERVICE_TIMEOUT_MSG); msg.obj = proc; mAm.mHandler.sendMessageAtTime(msg, psr.shouldExecServicesFg() ? (nextTime+SERVICE_TIMEOUT) : (nextTime + SERVICE_BACKGROUND_TIMEOUT)); } } if (anrMessage != null ) { mAm.mAnrHelper.appNotResponding(proc, anrMessage); }
最终会调用AnrRecord中的 appNotResponding
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 private static class AnrRecord { AnrRecord(ProcessRecord anrProcess, String activityShortComponentName, ApplicationInfo aInfo, String parentShortComponentName, WindowProcessController parentProcess, boolean aboveSystem, String annotation) { } void appNotResponding (boolean onlyDumpSelf) { mApp.mErrorState.appNotResponding(mActivityShortComponentName, mAppInfo, mParentShortComponentName, mParentProcess, mAboveSystem, mAnnotation, onlyDumpSelf); } }
其中ProcessErrorStateRecord是一个很关键的类,这里dump出了开头的日志,并且将dump出了anr文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 void appNotResponding (String activityShortComponentName, ApplicationInfo aInfo, String parentShortComponentName, WindowProcessController parentProcess, boolean aboveSystem, String annotation, boolean onlyDumpSelf) { ... StringBuilder info = new StringBuilder(); info.setLength(0 ); info.append("ANR in " ).append(mApp.processName); if (activityShortComponentName != null ) { info.append(" (" ).append(activityShortComponentName).append(")" ); } info.append("\n" ); info.append("PID: " ).append(pid).append("\n" ); if (annotation != null ) { info.append("Reason: " ).append(annotation).append("\n" ); } if (parentShortComponentName != null && parentShortComponentName.equals(activityShortComponentName)) { info.append("Parent: " ).append(parentShortComponentName).append("\n" ); } if (errorId != null ) { info.append("ErrorId: " ).append(errorId.toString()).append("\n" ); } info.append("Frozen: " ).append(mApp.mOptRecord.isFrozen()).append("\n" ); ... File tracesFile = ActivityManagerService.dumpStackTraces(firstPids, isSilentAnr ? null : processCpuTracker, isSilentAnr ? null : lastPids, nativePids, tracesFileException, offsets, annotation); if (mService.mUiHandler != null ) { Message msg = Message.obtain(); msg.what = ActivityManagerService.SHOW_NOT_RESPONDING_UI_MSG; msg.obj = new AppNotRespondingDialog.Data(mApp, aInfo, aboveSystem); mService.mUiHandler.sendMessageDelayed(msg, anrDialogDelayMs); } }
AMS 中获取/data/anr/anr_xxxx_xx_xx 文件路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 public static final String ANR_TRACE_DIR = "/data/anr" ; static File dumpStackTraces (ArrayList<Integer> firstPids, ProcessCpuTracker processCpuTracker, SparseArray<Boolean> lastPids, ArrayList<Integer> nativePids, StringWriter logExceptionCreatingFile, long [] firstPidOffsets, String subject) { .... final File tracesDir = new File(ANR_TRACE_DIR); File tracesFile; try { tracesFile = createAnrDumpFile(tracesDir); } catch (IOException e) { return null ; } Pair<Long, Long> offsets = dumpStackTraces( tracesFile.getAbsolutePath(), firstPids, nativePids, extraPids); if (firstPidOffsets != null ) { if (offsets == null ) { firstPidOffsets[0 ] = firstPidOffsets[1 ] = -1 ; } else { firstPidOffsets[0 ] = offsets.first; firstPidOffsets[1 ] = offsets.second; } } return tracesFile; } static final String ANR_FILE_PREFIX = "anr_" ; private static synchronized File createAnrDumpFile (File tracesDir) throws IOException { if (sAnrFileDateFormat == null ) { sAnrFileDateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS" ); } final String formattedDate = sAnrFileDateFormat.format(new Date()); final File anrFile = new File(tracesDir, ANR_FILE_PREFIX + formattedDate); }
Debug
1 2 3 4 5 6 7 8 9 10 public static native boolean dumpJavaBacktraceToFileTimeout (int pid, String file, int timeoutSecs) ;