简介
xCrash是爱奇艺开源的在android平台上面捕获异常的开源库。xCrash能为安卓 APP提供捕获Java崩溃异常,native崩溃异常和ANR异常。
xCrash 能在 App 进程崩溃或 ANR 时,在你指定的目录中生成一个 tombstone 文件(格式与安卓系统的 tombstone 文件类似)。
xCrash项目地址:
github:https://github.com/iqiyi/xCrash
gitee:https://gitee.com/caikelun/xCrash
xCrash源码结构
通过git获取xCrash源码,可以获知xcrash分为两个module,两个module分为是xcrash_lib,xcrash_sample。xcrash_lib是核心库,xcrash_sample是提供的测试工程。
xcrash_lib工程结构如下:
下面对结构进行简单的介绍:
ActivityMonitor:对app应用的activity通过list进行管理的工具类。
AnrHandler:anr异常捕获处理器。
DefaultLogger:xcrash库默认的日志输出接口,默认为通过android.util.Log输出日志。
Errno:xcrash常见的错误码。
FileManager:异常日志管理器,负责创建异常日志文件和清除过期的异常日志文件。
ICrashCallback:异常回调接口。
ILibLoader:so库加载回调接口。
ILogger:xcrash日志输出接口,DefaultLogger是其实现类。
JavaCrashHandler:java异常处理器。
NativeHandler:native异常处理器
TombstoneManager和TombstoneParser:异常日志分析器
Util:工具类,提供java异常的输出的基本信息,判断终端是否是root状态,获取内存信息等等。
Version:xcrash的版本信息。
XCrash:xcrash提供捕获异常的配置和初始化的功能。
Java异常捕获
xCrash捕获Java异常的处理器类为JavaCrashHandler。JavaCrashHandler是UncaughtExceptionHandler的子类。UncaughtExceptionHandler是java系统提供用来处理未捕获全局异常。
JavaCrashHandler
JavaCrashHandler是单例模式。
class JavaCrashHandler implements UncaughtExceptionHandler{
private static final JavaCrashHandler instance = new JavaCrashHandler();
private JavaCrashHandler() {
}
static JavaCrashHandler getInstance() {
return instance;
}
}
JavaCrashHandler初始化接口
JavaCrashHandler提供initialize接口,用于JavaCrashHandler初始化。JavaCrashHandler初始化的主要功能有:
- 保存APP应用信息。包括进程ID,进程名,应用版本。
- Java异常输出配置,包括输出日志路径,是否抛出异常,配置输出内容。
void initialize(int pid, String processName, String appId, String appVersion, String logDir, boolean rethrow,
int logcatSystemLines, int logcatEventsLines, int logcatMainLines,
boolean dumpFds, boolean dumpAllThreads, int dumpAllThreadsCountMax, String[] dumpAllThreadsWhiteList,
ICrashCallback callback){
}
JavaCrashHandler异常处理接口
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
if (defaultHandler != null) {
// xcrash不处理异常,采用默认的异常处理机制
Thread.setDefaultUncaughtExceptionHandler(defaultHandler);
}
try {
// 处理Java异常
handleException(thread, throwable);
} catch (Exception e) {
XCrash.getLogger().e(Util.TAG, "JavaCrashHandler handleException failed", e);
}
if (this.rethrow) {
// java默认异常处理,抛出异常
if (defaultHandler != null) {
defaultHandler.uncaughtException(thread, throwable);
}
} else {
// 关闭进程
ActivityMonitor.getInstance().finishAllActivities();
Process.killProcess(this.pid);
System.exit(10);
}
}
从源码可知,处理的核心接口为handleException。handleException的源码如下
private void handleException(Thread thread, Throwable throwable){
...
// 1. 通知native,anr异常处理器,java异常发生,其他异常处理器停止工作
NativeHandler.getInstance().notifyJavaCrashed();
AnrHandler.getInstance().notifyJavaCrashed();
// 2. 创建异常日志文件
File logFile = null;
try {
// 异常日志文件的命名规则
String logPath = String.format(Locale.US, "%s/%s_%020d_%s__%s%s", logDir, Util.logPrefix, startTime.getTime() * 1000, appVersion, processName, Util.javaLogSuffix);
logFile = FileManager.getInstance().createLogFile(logPath);
} catch (Exception e) {
XCrash.getLogger().e(Util.TAG, "JavaCrashHandler createLogFile failed", e);
}
// 获取java 异常输出
String emergency = null;
try {
// 应用基本信息,和java异常堆栈
emergency = getEmergency(crashTime, thread, throwable);
} catch (Exception e) {
XCrash.getLogger().e(Util.TAG, "JavaCrashHandler getEmergency failed", e);
}
// 3.异常日志写入文件
if (logFile != null){
// 3.1 写入emergency,java异常信息
// 3.2 logcat 写入异常文件中 logcat -b main; logcat -b event; logcat -b system
// 3.3 输出APP应用进程的文件描述符信息
// 3.4 输出内存信息
// 3.5 输出其他线程信息
}
}
Java异常整体比较简单,可以通过源码进行直观的分析。后续会新增native异常和anr异常的分析。