本篇文章主要介绍 Android 9.0 Crash 机制部分知识点 , 通过阅读本篇文章 , 您将收获以下内容:
一、Crash 概述Android 9.0 Crash 机制调用链
二、Crash处理流程
三、handleApplicationCrash处理分析
四、handleApplicationCrashInner 处理分析
五、APP Error info分析
六、makeAppCrashingLocked处理分析
七、startAppProblemLocked处理分析
八、stopFreezingAllLocked处理分析
/frameworks/base/core/JAVA/com/android/internal/os/RuntimeInit.java/frameworks/base/core/java/android/app/ActivityManagerNative.java (含内部类AMP)/frameworks/base/core/java/android/app/ApplicationErrorReport.java/frameworks/base/services/core/java/com/android/server/ - am/ActivityManagerService.java - am/ProcessRecord.java - am/ActivityRecord.java - am/ActivityStackSupervisor.java - am/ActivityStack.java - am/ActivityRecord.java - am/BroadcastQueue.java - wm/WindowManagerService.java/libcore/libart/src/main/java/java/lang/Thread.java一、Crash 概述App Crash (全称Application Crash), 对于Crash可分为Native Crash和 Framework Crash(包含app crash在内) , 对于Crash相信很多app开发者都会遇到 , 那么上层什么时候会出现Crash呢 , 系统又是如何处理Crash的呢 。例如 , 在app大家经常使用try...catch语句 , 那么如果没有有效catch exception , 就是导致应用Crash , 发生没有catch exception , 系统便会来进行捕获 , 并进入Crash流程 。如果你是从事Android系统开发或者架构相关工作 , 或者遇到需要解系统性的疑难杂症 , 那么很有必要了解系统Crash处理流程 , 知其然还需知其所以然;如果你仅仅是App初级开发 , 可能本文并非很适合阅读 , 整个系统流程错综复杂 。
在Android系统启动系列文章 , 已讲述过上层应用都是由Zygote fork孵化而来 , 分为system_server系统进程和各种应用进程 , 在这些进程创建之初会设置未捕获异常的处理器 , 当系统抛出未捕获的异常时 , 最终都交给异常处理器 。
- 对于system_server进程:system_server启动过程中由RuntimeInit.java的commonInit方法设置UncaughtHandler , 用于处理未捕获异常;
- 对于普通应用进程:进程创建过程中 , 同样会调用RuntimeInit.java的commonInit方法设置UncaughtHandler 。
crash流程的方法调用关系如下:
AMP.handleApplicationCrash AMS.handleApplicationCrash AMS.findAppProcess AMS.handleApplicationCrashInner AMS.addErrorToDropBox AMS.crashApplication AMS.makeAppCrashingLocked AMS.startAppProblemLocked ProcessRecord.stopFreezingAllLocked ActivityRecord.stopFreezingScreenLocked WMS.stopFreezingScreenLocked WMS.stopFreezingDisplayLocked AMS.handleAppCrashLocked mUiHandler.sendMessage(SHOW_ERROR_MSG)Process.killProcess(Process.myPid());System.exit(10);二、Crash处理流程RuntimeInit.java类的 main方法会调用commonInit()方法 。
public static final void main(String[] argv) { enableDdms(); if (argv.length == 2 && argv[1].equals("application")) { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application"); redirectLogStreams(); } else { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting tool"); } // AP Crash 处理流程初始化 commonInit(); // Native Crash 处理流程初始化 nativeFinishInit(); if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!"); }那么接下来以commonInit()方法为起点来展开说明 。
1. RuntimeInit.commonInit
RuntimeInit.java
protected static final void commonInit() { /* * set handlers; these apply to all threads in the VM. Apps can replace * the default handler, but not the pre handler. */ LoggingHandler loggingHandler = new LoggingHandler(); // app不能 替换 setUncaughtExceptionPreHandler Thread.setUncaughtExceptionPreHandler(loggingHandler); // 将异常处理器handler对象赋给Thread成员变量, Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler)); ... ... }接下来我们看看LoggingHandler的实现 。LoggingHandler实现 Thread.UncaughtExceptionHandler 方法 。
private static class LoggingHandler implements Thread.UncaughtExceptionHandler { public volatile boolean mTriggered = false; @Override public void uncaughtException(Thread t, Throwable e) { mTriggered = true; //保证crash处理过程不会重入 if (mCrashing) return; //mApplicationObject等于null,一定不是普通的app进程.//但是除了system进程, 也有可能是shell进程,//即通过app_process + 命令参数 的方式创建的进程. if (mApplicationObject == null && (Process.SYSTEM_UID == Process.myUid())) {//系统 进程Crash打印的Log 信息 /** 发生 系统Crash 时候可以搜索 关键字 FATAL EXCEPTION IN SYSTEM PROCESS **/ Clog_e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e); } else { /** 发生 APP Crash 时候可以搜索 关键字 FATAL EXCEPTION **/ StringBuilder message = new StringBuilder(); message.append("FATAL EXCEPTION: ").append(t.getName()).append("n"); final String processName = ActivityThread.currentProcessName(); if (processName != null) { message.append("Process: ").append(processName).append(", "); } message.append("PID: ").append(Process.myPid()); Clog_e(TAG, message.toString(), e); } } }
推荐阅读
- 几款实用的Android Studio 插件给你推荐一下
- Android Studio Debug 的 9 个小技巧
- JavaScript 中对于Promise的理解
- 在 Linux 上用 strace 来理解系统调用
- 深入理解Java继承的实现原理
- android Flutter 工程结构和资源文件分辨率相关的图片文件放哪儿
- 现象学家所理解的现象 世界上科学家无法解释的现象
- 800 字彻底理解 Go语言 指针
- HDFS架构详解!会了这个,hadoop还难理解吗?
- 如何深入浅出理解数据仓库建模?