崩溃优化之Java层crash原理分析

一、造成系统崩溃(crash)的原因是什么?

未捕获的异常

Java层面,和Native层面

在我们平常操作中,如果有未捕获的异常,会导致系统崩溃,这个崩溃本质上是人为操作的,人为去操作系统主动退出(后面讲源码的地方可以看到)。

ANR

系统因为线程阻塞问题,导致的无响应。

WTF(What a Terrible Failure)

一般指,系统中自己编码没有按照android要求进行,例如发送未受保护的广播、启动的Activity未在注册文件里注册等等;

这个一般不用太关注,主要写代码按标准来就行。


二、java层未捕获的异常是如何导致崩溃的

源码分析步骤1

首先我们先明确一个目的,我们的main函数的启用本身作为主线程存在,那么在我们想要探索系统到底如何处理异常,需要去关注到一个类Thread

在我们的程序代码中,如果存在一个异常,任何地方都没有去捕获处理它的话,它就会一路往上抛,最终来到main函数,如果main函数也没有处理这个异常,就会给到JVM来处理,JVM给到当前的线程Thread来处理。

源码分析步骤2

Thread类中,看到一段这样的函数dispatchUncaughtException()

注释翻译为:向处理程序发送未捕获的异常。此方法旨在仅由JVM调用;可以理解为,未处理的异常会走到这里来:

在上图我们可以看到官方明确告知,JVM在处理未经捕获的异常时,会调用当前dispatchUncaughtException函数进行处理,这个里面我们能看到一个类型为UncaughtExceptionHandler的类。

在上图的逻辑中我们可以看到如果没有设置uncaughtExceptionHandler,将使用线程所在的线程组(ThreadGroup来处理这个未捕获异常。线程组ThreadGroup实现了UncaughtExceptionHandler,所以可以用来处理未捕获异常。

源码分析步骤3

所以,我们重点来看ThreadGroup中,是如何来处理未捕获异常的:在Thread类的dispatchUncaughtException函数中,最后调用了getUncaughtExceptionHandler().uncaughtException(this, e); 我们知道这个getUncaughtExceptionHandler()返回的是ThreadGroup,所以我们来看ThreadGroup中的uncaughtException方法:

默认情况下,ThreadGroup处理未捕获异常的逻辑是:

  1. 首先将异常消息通知给父线程组(如果parent不为空的话)

  1. 然后尝试利用一个默认的defaultUncaughtExceptionHandler来处理异常;

  1. 如果没有默认的异常处理器则将错误信息输出打印到System.err

这里可以思考下,我们可以自定义一个异常处理类,继承下 Thread.UncaughtExceptionHandler,然后去处理未捕获的异常。记得需要手动去调用Thread.setUncaughtExceptionPreHandler()方法设置下,有了这个自定义异常处理类,就可以做相应的崩溃优化。

源码分析步骤4

回到Thread中,思考下:既然他是通过getDefaultUncaughtExceptionHandler来处理,现在我们并没有看到有相关的设置,但是在Thread中我们看到了他对外提供了对应的设置函数:Thread.setUncaughtExceptionPreHandler()

源码分析步骤5

思考下:系统是否会有地方默认给我们设置了uncaughtExceptionHandler?

因为从上面的源码看来,我们并没有看到有让系统直接崩溃掉的情况,因为默认是ThreadGroup去处理,他只不过是做了一个日志信息的记录,不会有退出的情况,那么肯定是有哪个地方默认设置了uncaughtExceptionHandler让系统退出的。

源码分析步骤6

来看下RuntimeInit这个类,zygote负责启动RuntimeInit进程(作用:app运行时环境初始化,用来初始化运行时的一系列信息,其中包含异常处理),它里面有个main方法

这里设置了默认的异常处理KillApplicationHandler。

源码分析步骤7

我们来看下KillApplicationHandler

重点来看 uncaughtException(Thread t, Throwable e)这个方法:

看到这里就知道了,默认的异常处理(杀进程)是在RuntimeInit进程作用:app运行时环境初始化,用来初始化运行时的一系列信息,其中包含异常处理)的main()方法里设置的。

小总结


三、AMS如何承接应用的异常信息上报?

在上面的源码分析步骤7我们知道了,在KillApplicationHandleruncaughtException()方法里,最终异常信息有一个AMS上报过程:

来看下ActivityManagerService.handleApplicationCrash()方法:

从上面可以看出,若传入appnull时,processName就设置为system_server意思是:如果没有来源默认判定是系统进程自己。接着看handleApplicationCrashInner(String eventType......)方法:

参数eventType是指事件类型,具体如下:

  • Java层未捕捉的异常:crash

  • ANR:anr

  • native层的异常:native_crash

现在我们看的是java的异常,所以这个类型传的是crash

接着看handleApplicationCrashInner()函数:

中间的可以先不管他们,这个可以理解为在进行系统日志输出,具体的处理是在addErrorToDropBox()函数中。

重点注意:无论是java crashnative_crashANR或是wtf最终都是来到这里,交由addErrorToDropBox()函数去处理。


四、DropBoxManager

addErrorToDropBox()函数和DropBoxManager有关,Android Dropbox 是 Android 在 Froyo(API level 8) 引入的用来持续化存储系统数据的机制。主要用于记录 Android 运行过程中, 内核, 系统进程, 用户进程等出现严重问题时的 log, 可以认为这是一个可持续存储的系统级别的 logcat。

记录位置:在data/system/dropbox中:

也就是说,我们想要看系统的崩溃日志,可以在这个文件路径下找。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中,可以通过以下步骤来生成crash_err: 1. 创建一个Java项目,并确保已安装Java开发工具包(JDK)。 2. 编写一个Java代码文件,以生成crash_err。以下是一个示例代码: ```java public class GenerateCrashErr { public static void main(String[] args) { int[] array = new int[5]; try { for (int i = 0; i <= array.length; i++) { array[i] = i; } } catch (ArrayIndexOutOfBoundsException e) { throw new RuntimeException("crash_err生成成功!"); } } } ``` 在这个示例代码中,我们创建了一个长度为5的整数数组。然后,我们试图通过一个for循环给数组的每个元素赋值。然而,由于循环的条件超出了数组的范围,就会抛出ArrayIndexOutOfBoundsException异常。在catch块中,我们将其重新抛出为一个RuntimeException,同时提供自定义的错误消息“crash_err生成成功!”。这个错误消息将作为crash_err的内容。 3. 将代码保存为GenerateCrashErr.java文件。 4. 打开终端或命令提示符窗口,并导航到保存GenerateCrashErr.java文件的目录。 5. 使用Java命令编译和运行该文件: ``` javac GenerateCrashErr.java java -jar GenerateCrashErr.jar ``` 6. 如果一切顺利,你将看到生成的crash_err信息。 请注意,这只是一个简单的示例来生成crash_err,并非真正的应用。在实际开发中,crash_err是一个不应该出现的错误,应该尽可能避免它的发生,并且在出现问题时提供有意义的错误消息。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值