稳定性 维度:Crash率,性能,业务可用性 重预防,稳监控 UV、PV 采集、处理(清洗、聚合、分类、趋势)、展示(数据还原、维度、版本分析)、预警 Crash优化治理 根据堆栈及现场信息分析原因 找共性:机型、OS、实验开关、资源包,考虑影响范围 线下复现、远程调试 Crash解决三步走 常规直接解、系统及Hook绕、疑难重点突破 常用代码原文地址:https://juejin.cn/post/6844903972587716621#heading-56
出现未捕获异常,导致出现异常退出,进程唯一
Thread.setDefaultUncaughtExceptionHandler();
获取主线程的堆栈信息:
Looper.getMainLooper().getThread().getStackTrace(); 复制代码
获取当前线程的堆栈信息:
Thread.currentThread().getStackTrace(); 复制代码
获取全部线程的堆栈信息:
Thread.getAllStackTraces(); 复制代码
反混淆:Mapping映射 Java Crash logcat日志流程,**应用层(logcat命令) --> liblog.so(hook liblog.so 中的 **__android_log_buf_write方法) --> logd(通过socket直接跟logd交互,底层使用 ring buffer 来存储数据。 Thread.getAllStackTraces()。第三方Crash监控工具如 Fabric、腾讯Bugly,都是以字符串拼接的方式将数组StackTraceElement[]转换成字符串形式,进行保存、上报或者展示。
优点:简单,兼容性好。
缺点:1.成功率不高,依靠系统接口在极端情况也会失败。2.7.0之后这个接口是没有主线程堆栈。3.使用Java层的接口需要暂停线程。
hook libart.so。通过hook ThreadList和Thread 的函数,获得跟ANR一样的堆栈。为了稳定性,需要在fork的子进程中执行。
优点:信息很全,基本跟ANR的日志一样,有native线程状态,锁信息等等。
缺点:黑科技的兼容性问题,失败时我们可以使用Thread.getAllStackTraces()兜底。
Crash流程 1、首先发生crash所在进程,在创建之初便准备好了defaultUncaughtHandler,用来处理Uncaught Exception,并输出当前crash的基本信息; 2、调用当前进程中的AMP.handleApplicationCrash;经过binder ipc机制,传递到system_server进程; 3、接下来,进入system_server进程,调用binder服务端执行AMS.handleApplicationCrash; 4、从mProcessNames查找到目标进程的ProcessRecord对象;并将进程crash信息输出到目录/data/system/dropbox; 5、执行makeAppCrashingLocked:- 创建当前用户下的crash应用的error receiver,并忽略当前应用的广播;
- 停止当前进程中所有activity中的WMS的冻结屏幕消息,并执行相关一些屏幕相关操作;
- 当1分钟内同一进程未发生连续crash两次时,则执行结束栈顶正在运行activity的流程;
- 当1分钟内同一进程连续crash两次时,且非persistent进程,则直接结束该应用所有activity,并杀死该进程以及同一个进程组下的所有进程。然后再恢复栈顶第一个非finishing状态的activity;
- 当1分钟内同一进程连续crash两次时,且persistent进程,则只执行恢复栈顶第一个非finishing状态的activity。
由于Crash进程中拥有一个Binder服务端ApplicationThread,而应用进程在创建过程调用attachApplicationLocked(),从而attach到system_server进程,在system_server进程内有一个ApplicationThreadProxy,这是相对应的Binder客户端。当Binder服务端ApplicationThread所在进程(即Crash进程)挂掉后,则Binder客户端能收到相应的死亡通知,从而进入binderDied流程。
Native Crash- 访问非法地址
- 地址对齐出错
- 发生程序主动abort



