结合源码深入理解Android Crash处理流程

应用程序crash在开发过程中还是很常见的,本文主要是从源码的角度去跟踪下Android对于crash的处理流程。App crash的全称:Application crash。而Crash又分为:native crash和framework crash(包含App Crash)。我们在平时开发的时候对于可能有异常的地方,一般都是用try-catch语句去catch 异常信息,但当没有有效的catc...
摘要由CSDN通过智能技术生成

应用程序crash在开发过程中还是很常见的,本文主要是从源码的角度去跟踪下Android对于crash的处理流程。App crash的全称:Application crash。而Crash又分为:native crash和framework crash(包含App Crash)。我们在平时开发的时候对于可能有异常的地方,一般都是用try-catch语句去catch 异常信息,但当没有有效的catch住的时候,就会导致应用crash,此时系统就会进行捕获,并进入到crash的流程。

《从源码角度看Android系统Zygote进程启动过程》一文中可知:system_server进程和上层应用程序的进程都是Zygote进程fork来的,而在这些进程创建的时候会设置未捕获异常的处理器,当系统中有未捕获的异常时候,就会交给异常器去处理。

无论是system_server进程还是应用程序进程都会在创建的过程中调用RuntimeInit.java的commonInit方法去做一些通用的初始化操作,其中就有设置默认的未捕捉异常处理器UncaughtHandler。

备注:本文将结合Android6.0的源码深入理解Android Crash处理流程

1. Android Crash 处理流程

下面以RuntimeInit.java的commonInit方法为起点对Crash流程进行跟踪分析。

1.1 RuntimeInit.java—>commonInit方法

代码路径:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

深入到commonInit的方法中:

private static final void commonInit() {
    if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");

	//设置默认的未捕获异常处理器
    Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler()); //注释1

	...省略...
}

注释解析:

  • 注释1处就是给要创建的进程设置未捕获异常处理器。setDefaultUncaughtExceptionHandler是将异常处理器的handler对象赋给Thread的成员变量。

下面继续跟踪看UncaughtHandler对象实例化的过程!!!

1.2 RuntimeInit.java—>静态内部类UncaughtHandler

代码路径:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

深入到静态内部类UncaughtHandler中:

private static class UncaughtHandler implements Thread.UncaughtExceptionHandler {
    public void uncaughtException(Thread t, Throwable e) {
        try {
            //确保crash过程不会重复进入
            if (mCrashing) return;
            mCrashing = true;

			//判断是否为系统进程
            if (mApplicationObject == null) {
				//系统进程
                Clog_e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e); //注释1
            } else {
				//普通进程
				// 注释2
                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);
            }

            // 注释3
            ActivityManagerNative.getDefault().handleApplicationCrash(
                    mApplicationObject, new ApplicationErrorReport.CrashInfo(e));
        } catch (Throwable t2) {
            try {
                Clog_e(TAG, "Error reporting crash", t2);
            } catch (Throwable t3) {
                // Even Clog_e() fails!  Oh well.
            }
        } finally {
            // 注释4
            Process.killProcess(Process.myPid());
            System.exit(10);
        }
    }
}

注释解析:

  • 注释1处当是系统进程Crash信息时:

    1. 开头是: *** FATAL EXCEPTION IN SYSTEM PROCESS:[线程名]

    2. 输出发生Crash时的调用栈信息

  • 注释2处当是普通应用进程时:

    1. 开头是:FATAL EXCEPTION:[线程名]

    2. 然后是:Process:[进程名],PID:[进程id]

    3. 输出发生Crash时的调用栈信息

  • 注释3处是启动Crash的弹框。而ActivityManagerNative.getDefault()返回的是ActivityManagerProxy(简称AMP),AMP经过binder调用最后会交给ActivityManagerService(简称AMS),即Crash的弹框最终调用的是AMS的handleApplicationCrash方法。其中传入的参数new ApplicationErrorReport.CrashInfo(e)的作用是将crash信息文件名、类名、方法名、对应行号和异常信息封装到CrashInfo对象中。

    <
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值