Android崩溃_第1张图片

ARPU: 一个时间段内运营商从每个用户所得到的收入;

DAU: 日活跃用户,MAU: 月活跃用户

Android崩溃_第2张图片

Android崩溃_第3张图片

Java Crash 应用程序层崩溃

Java的异常体系:
https://developer.android.com/reference/java/lang/Throwable.html
Throwable继承Object类。
Throwable有2个子类,Error和Exception。

Exception分为:
checked exception(可检查异常)、
unchecked exception(非检查异常,或运行时异常RuntimeException)。
checked exception:编译时,java编译器强制程序员必须进行捕获处理。比如IOException
RuntimeException:运行时产生的异常,比如NullPointerException、IndexOutOfBoundsException、
IllegalStateException等等.....

Android崩溃_第4张图片

java层异常处理(一)
Thread.UncaughtExceptionHandler是一个接口,它提供如下的方法,让我们自定义处理程序。
当一个线程因为没有捕捉的异常导致的突然终止时,该接口被唤醒。 
当一个线程因为不能捕捉的异常将要终止的时候,JVM会调用getUncaughtExceptionHandler方法查找扎个
线程对应的指定UncaughtExceptionHandler对象,并且回调这个对象的uncaughtException方法。如果这个
线程没有指定的UncaughtExceptionHandler对象,那么将ThreadGroup对象作为UncaughtExceptionHandler
对象,因为ThreadGroup类实现了Thread.UncaughtExceptionHandler接口;会调用顶层ThreadGroup的那个
默认的UncaughtExceptionHandler对象的uncaughtException方法。

java层异常处理(二)
异常处理是怎么样的呢?
1.当发生异常的时候,比如调用throw new Exception()没有捕获,
进入产生异常的线程(Thread类)的dispatchUncaughtException方法。
2.其中uncaughtExceptionHandler是UncaughtExceptionHandler的对象,
而group是ThreadGroup的对象。
3.如果我们通过setDefaultUncaughtExceptionHandler()
方法来设置指定的UncaughtExceptionHandler对象,就直接调用这个的
UncaughtExceptionHandler的uncaughtException方法,JVM退出。
4.如果我们没有通过setDefaultUncaughtExceptionHandler来设置指定的
UncaughtExceptionHandler对象,所以uncaughtExceptionHandler为空,
那么调用group的uncaughtException方法,因为ThreadGroup实现了

UncaughtExceptionHandler接口。

parent是ThreadGroup的对象,ThreadGroup中还可以有ThreadGroup对象。
程序会先找到顶层的ThreadGroup对象。直接进入else分支,如果设置了
默认UncaughtExceptionHandler对象,那么调用默认的
UncaughtExceptionHandler对象的uncaughtException方法,JVM退出。如果
没有设置默认的UncaughtExceptionHandler对象,那么就打印出异常信息,

最后虚拟机会退出。

Android崩溃_第5张图片

C层异常处理(一)
首先,需要理解几个概念:
1. 进程
Linux内核在启动过程中,创建第一个用户空间Init进程PID = 1,用于启动一些本地进程,比如Zygote进程。
创建一个名为Kthreadd的内核进程PID=2,用于创建内核空间其他进程。
一个进程有一个PID,还会有一个PPID(parent PID)来存储的父进程PID。
Zygote进程是一个专门用于创建Java进程的本地进程。
如果我们循着android应用进程的PPID不断向上追溯的话,总会发现其源头是init进程。

所以说,所有的进程也构成一个以init为根的树状结构。

2.Signal
信号是发送给进程或进程组的一个非常小的消息,通常只包含信号编号;
现在的系统可以附带siginfo信息,见sigaction的SA_SIGINFO标识。
信号主要有以下两个目的:
1.让进程知道出现某异步事件
2.出现异步事件,让进程能做出相应的处理(通过提供信号处理函数,由内核自动调用)


信号的种类:

1.可靠性方面:可靠信号与不可靠信号;
2.时间的关系上:实时信号与非实时信号。

不可靠信号:Linux信号机制基本上是从Unix系统中继承过来的。
早期Unix系统中的信号机制比较简单和原始,信号值小于SIGRTMIN(32)的信号都是不可靠信号。
可靠信号:信号值位于SIGRTMIN(32)和SIGRTMAX(64)之间的信号都是可靠信号,可靠信号克服了信号可能丢失的问题。

非实时信号都不支持排队,都是不可靠信号;实时信号都支持排队,都是可靠信号。

Android崩溃_第6张图片

C层异常处理(二)
信号生命周期:
1.信号产生:内核更新目标进程数据结构,表示出现某异步事件
2.信号pending:信号产生但是未被传递出去,叫信号pending;
   主要是因为信号产生、信号传递是分为两个阶段的(信号在内核态返回用户态时传递,信号产生是在任意时间),所以之间存在延迟;
   同时信号阻塞会大大加长信号pending的时间;
3.信号传递:内核通过改变目标进程运行状态并执行信号的handler,来让目标进程对信号标识的异步事件做相应的处理
信号产生,主要有以下4种情况会产生signal:
1.硬件异常:当硬件检测到异常时;如SIGFPE(除0异常等),SIGSEGV(非法内存访问)
2.软件通知:当某事发生需要通知用户进程时;如信号SIGURG(网络连接中出现out-of-band数据,发送该信号),
   SIGPIPE(当往没有读者的管道中写数据时,发送该信号)
3.终端信号:当按下某些终端键时;如SIGINT(ctrl+c)
4.kill系统调用:当通过kill系统调用向其他进程发送信号时;如kill SIGUSR1 pid(kill命令调用kill系统调用)
 信号pending,主要有以下因素会影响信号pending的时间:
1.内核通常只传递当前进程的信号;当CPU从内核态切换到用户态时,内核会传递当前进程(占用该CPU的进程)的信号,而不会传递其它进程的信号。其它进程占用CPU后内核才会传递信号给该进程。
2.某信号可以被阻塞,直到该信号取消阻塞后,该信号才会被传递
3.当在执行某信号的处理handler时,内核会自动阻塞该信号直到该信号的处理完成;所以信号被处理时,该信号的再次出现不会打断信号处理,所以信号的处理handler不需要可重入。 
信号传递,当内核传递信号时,进程可以有如下action:
1.显式的忽略该信号
2.执行内核预定的默认动作,Terminate、Dump、Ignore、Stop、Continue

3.执行进程提供的自定义信号处理handler

Android崩溃_第7张图片

Android崩溃_第8张图片

结论:java层的崩溃,最后发送signal 9信号杀死继进程,是不能捕获、阻塞或忽略的。

这是Runtime崩溃与C层崩溃最直接的区别。

breakpad

Android崩溃_第9张图片

Android崩溃_第10张图片

Android崩溃_第11张图片


更多相关文章

  1. android的进程间通信aidl
  2. Android IPC进程通信——Messager方式
  3. Android进程保活(常驻内存)
  4. android init进程解析init.rc过程
  5. android启动之init进程详解
  6. Android Framework内核之旅
  7. Linux下Android内核源码下载

随机推荐

  1. 常见问题汇总一
  2. Android根据电话号码取得联系人姓名及头
  3. 基于百度推送android notification的使用
  4. Android(安卓)模糊效果实现
  5. Android(安卓)bug之 opencv CascadeClass
  6. Android状态栏完全透明和改变状态栏颜色
  7. 通用android studio gradle 文件(电商商家
  8. Android(安卓)uses-permission 大全
  9. Android之NetworkOnMainThreadException
  10. android 控件属性