天天看點

xCrash捕獲Java異常簡介xCrash源碼結構Java異常捕獲

簡介

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工程結構如下:

xCrash捕獲Java異常簡介xCrash源碼結構Java異常捕獲

下面對結構進行簡單的介紹:

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初始化的主要功能有:

  1. 儲存APP應用資訊。包括程序ID,程序名,應用版本。
  2. 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異常的分析。