项目开发中哪些情况会引发崩溃:

Java 崩溃;
Java 崩溃就是在 Java 代码中,出现了未捕获异常,导致程序异常退出。

native 崩溃;
一般都是因为在 Native 代码中访问非法地址,也可能是地址对齐出现了问题,或者发生了程序主动 abort , 这些都会产生相应的 signal 信号,导致程序异常退出。

ANR;
死锁;
IO 问题;
主线程耗时操作;
频繁大量 GC.

今天咱们主要讲的NativeCrash,主要解决方案:

1、bugly符号表 符号表路径

符号表是内存地址与函数名、文件名、行号的映射表。符号表元素如下所示:
<起始地址> <结束地址> <函数> [<文件名:行号>]

为什么要配置符号表?
快速并准确地定位用户APP发生Crash的代码位置,Bugly使用符号表对APP发生Crash的程序堆栈进行解析和还原。
举一个例子:

2、基于breakpad:

APP中接入提供的SDK,包含一个通用SO和一个JAR,当APP中发生NDK崩溃时,会在手机端生成一个dmp文件,待下次APP重启后,将此dmp文件上传至服务端,在服务端进行解析、分类、聚合、可读展示等过程

3、基于linux信号处理的轻量级方法:

Native层代码发生崩溃崩溃时,会发送异常signal,系统捕获到异常signal后,回调信号异常处理函数(需事先注册),在异常处理函数中获取C层崩溃堆栈数据,通过JNI回调至JAVA层,进行解析、上传等操作

要实现 Native Crash 的收集,主要有四个重点:
知道 Crash 的发生;捕获到 Crash 的位置;获取 Crash 发生位置的函数调用栈;数据能回传到服务器。

两种方法各有优缺点,基于breakpad的方法体量较大,但获取的信息较全面。基于异常信号处理方法体量小,但信息不全面,只有崩溃线程的堆栈信息,不利于定位多线程崩溃的问题。

breakpad 编译及使用 源文

这里推荐大家使用 Google 开源 的 Breakpad, 为什么呢?因为它是目前 Native 崩溃捕获中最为成熟的方案
如果你对 Native 崩溃机制的一些基本知识还不是很熟悉,可以看一下Android 平台 Native 代码的崩溃捕获机制及实现

1. 获取 breakpad 源码 GitHub下载

2. 执行安装 breakpad

1. cd breakpad 目录
2. 直接命令窗口输入:
./configure && make

执行完之后会生成 src/processor/minidump_stackwalk 等文件,待会 dmp -> txt 会用到这个文件。

3. CMake 编译源码

build配置

apply plugin: 'com.android.library'android {.....defaultConfig {....externalNativeBuild {cmake {cppFlags "-std=c++11"}}ndk {abiFilters "armeabi-v7a", "arm64-v8a", "x86"}}....externalNativeBuild {cmake {path "src/main/cpp/CMakeLists.txt"}}
}dependencies {implementation fileTree(dir: 'libs', include: ['*.jar'])
}

把 breakpad/src 源码导致 AS 中 CMake 配置好之后直接在 AS/Build/make break-build 之后就能生成动态 so 库了。

注意:下载的源码缺少 lss 目录,可以点击下载获取

4. 编写初始化 breakpad

#include <stdio.h>
#include <jni.h>
#include <android/log.h>#include "client/linux/handler/exception_handler.h"
#include "client/linux/handler/minidump_descriptor.h"#define LOG_TAG "dodoodla_crash"#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
#define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)bool DumpCallback(const google_breakpad::MinidumpDescriptor &descriptor,void *context,bool succeeded) {ALOGD("===============crrrrash================");ALOGD("Dump path: %s\n", descriptor.path());return succeeded;
}/** java 代码中调用*/
extern "C"
JNIEXPORT void JNICALL
Java_com_devyk_crash_1module_CrashUtils_initBreakpadNative(JNIEnv *env, jclass type,jstring path_) {const char *path = env->GetStringUTFChars(path_, 0);// TODOgoogle_breakpad::MinidumpDescriptor descriptor(path);static google_breakpad::ExceptionHandler eh(descriptor, NULL, DumpCallback, NULL, true, -1);env->ReleaseStringUTFChars(path_, path);
}JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {JNIEnv *env;if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {return JNI_ERR;}return JNI_VERSION_1_6;
}

生成 dmp 文件并定位 crash

1. 在 app 模块中写崩溃代码

/**

  • 引起 crash
    */
    void Crash() {
    volatile int *a = (int *) (NULL);
    *a = 1;
    }

extern “C”
JNIEXPORT void JNICALL
Java_com_devyk_ykcrash_MainActivity_testCrash(JNIEnv *env, jclass type) {

// TODO
Crash();

}

2. init native crash 捕获

//配置 native 崩溃捕获
CrashUtils.initCrash(String nativeCrashPath);

3. 制造 Crash 并生成 xxx.dmp 文件

4. dmp to txt

1、将 breakpad/src/processor/minidump_stackwalk copy 到一个单独的文件下

2、执行命令 to txt

//格式
./minidump_stackwalk xxx.dmp >xxx.txt

//例子
./minidump_stackwalk /Users/devyk/Data/Project/sample/tempFile/nativeCrash.dmp >crashLog2.txt

3、查看 txt 文件到底是什么?

Operating system: Android0.0.0 Linux 4.9.148 #1 SMP PREEMPT Wed Jun 26 04:38:26 CST 2019 aarch64
CPU: arm648 CPUsGPU: UNKNOWNCrash reason:  SIGSEGV /SEGV_MAPERR
Crash address: 0x0
Process uptime: not available//crash 发生线程
Thread 0 (crashed)//这里的 libcrash-lib.so + 0x5f0 很重要。告诉了我们在哪个 so 发生崩溃,在具体哪个位置发生崩溃。这里先记住 0x5f0 这个值。0  libcrash-lib.so + 0x5f0 x0 = 0x00000078d4ac5380    x1 = 0x0000007fe01fd9d4x2 = 0x0000007fe01fda00    x3 = 0x00000078d453ecb8x4 = 0x0000000000000000    x5 = 0x00000078d4586b94x6 = 0x0000000000000001    x7 = 0x0000000000000001x8 = 0x0000000000000001    x9 = 0x0000000000000000x10 = 0x0000000000430000   x11 = 0x00000078d49396d8x12 = 0x000000795afcb630   x13 = 0x0ef1a811d0863271x14 = 0x000000795aede000   x15 = 0xffffffffffffffffx16 = 0x00000078b8cb5fe8   x17 = 0x00000078b8ca55dcx18 = 0x0000000000000000   x19 = 0x00000078d4a15c00x20 = 0x0000000000000000   x21 = 0x00000078d4a15c00x22 = 0x0000007fe01fdc90   x23 = 0x00000079552cb12ax24 = 0x0000000000000000   x25 = 0x000000795b3125e0x26 = 0x00000078d4a15ca0   x27 = 0x0000000000000000x28 = 0x0000007fe01fd9d0    fp = 0x0000007fe01fd9a0lr = 0x00000078b8ca5614    sp = 0x0000007fe01fd980

4、基于 dmp to txt 里面的 libcrash-lib.so + 0x5f0 信息,转换为具体哪个函数,哪行报的错

根据 txt 提示的信息 aarch64 CPU: arm64 那么我们就在当前使用的 NDK 版本找到 /Users/devyk/Data/Android/NDK/android-ndk-r17c/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/aarch64-linux-android-addr2line这个路径,使用下面的命令找到具体报错的地方

//1. 格式
aarch64-linux-android-addr2line -f -C -e [根据 txt 信息拿到具体报错的 so] [根据 txt 文件信息拿到具体报错的值]

//2. 示例
/Users/devyk/Data/Android/NDK/android-ndk-r17c/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64/bin/aarch64-linux-android-addr2line -f -C -e /Users/devyk/Data/Project/sample/github_code/YKCrash/app/build/intermediates/transforms/mergeJniLibs/debug/0/lib/arm64-v8a/libcrash-lib.so 0x5f0

//报错的函数
Crash()
//当前 cpp 报错的行数
/Users/devyk/Data/Project/sample/github_code/YKCrash/app/src/main/cpp/crash.cpp:10

我们看下 cpp 10 行具体是什么

这里不用想,肯定会 crash。

到这里我们已经捕获到了 native 层崩溃日志。

NativeCrash崩溃异常处理方案相关推荐

  1. Android网络连接异常处理方案

    Android网络连接异常处理方案 参考文章: (1)Android网络连接异常处理方案 (2)https://www.cnblogs.com/yangcong/p/3523021.html 备忘一下 ...

  2. 第八节:Task的各类TaskTResult返回值以及通用线程的异常处理方案。

    一. Task的各种返回值-Task<TResult> PS: 在前面章节,我们介绍了Task类开启线程.线程等待.线程延续的方式,但我们并没有关注这些方式的返回值,其实他们都是有返回值的 ...

  3. 第八节:Task的各类TaskTResult返回值以及通用线程的异常处理方案

    一. Task的各种返回值-Task<TResult> PS: 在前面章节,我们介绍了Task类开启线程.线程等待.线程延续的方式,但我们并没有关注这些方式的返回值,其实他们都是有返回值的 ...

  4. Selenium UnreachableBrowserException异常处理方案

    Selenium UnreachableBrowserException异常处理方案 异常信息 解决方法 原理 代码 Selenium版本4.0.0-alpha-6 客户端代码以Java为例 异常信息 ...

  5. SSM整合-异常处理器及项目异常处理方案

    目录 一.异常处理器 二.项目异常处理方案 项目异常分类 项目异常处理方案 项目异常处理 一.异常处理器 程序开发过程中不可避免的会遇到异常现象 出现异常现象的常见位置与常见诱因如下: ■ 框架内部抛 ...

  6. APS软件有哪些排程规则?有何异常处理方案?

    一.什么是APS系统 APS系统是什么意思?起什么作用?随着企业规模不断扩大,在经营管理方面会面临各种各样的问题,为了帮助解决此类问题,很多公司都会引入APS高级排程系统帮助进行生产管理的优化. AP ...

  7. 寿险业务系统异常处理方案

    我们的系统使用的java语言开发,基于Spring框架搭建的业务中台,在讨论业务系统异常处理策略之前,先把java的异常机制进行简单说明. 一.Java的异常机制 1.Java异常分类 [Error] ...

  8. IBM服务器raid5崩溃数据恢复方案及过程

    概述: IBM X3850服务器,5块73G SAS硬盘,其中4块组成一个RAID5,另一块做为热备盘(Hot-Spare),3号盘早已经离线,但热备盘未自动激活rebuild(原因不明),之后2号盘 ...

  9. springboot定时任务中异常处理方案

    1.场景描述      2.处理方案      3.相关代码      4.注意事项说明 1.场景描述 现有一个会员过期处理需求,需要定时进行处理,一般情况下业务都会处理成功.但是在代码逻辑正确的情况 ...

  10. GC导致的崩溃处理方案

    UE4垃圾回收处理中,对象在使用它,此时可能导致崩溃,因为GC处理,指向地址非法. 如以下崩溃: 我们使用物体材质SetScalarParameterValue时候,此时GC,可能崩溃(游戏结束跳图. ...

最新文章

  1. 4104 oracle 数据文件名,Oracle 11g 常遇到ora-01034错误,这是为什么?
  2. python面试总结
  3. 如何获取filecoin_Filecoin如何获取更大的出块机会?
  4. MySQL动态行转列
  5. 使用jQuery插件realshadow实现超酷真实阴影效果
  6. 51CTO的技术门诊谈OSSIM
  7. UE4 查看打包文件内容
  8. ubuntu下,apt的参数使用,很实用呦
  9. NYOJ--364--田忌赛马
  10. plc和变频器通讯接线图详解
  11. 怎么算特征值和特征矩阵?
  12. 女人健身操必知的健康常识
  13. 困牛放牧(Sleepy Cow Herding)
  14. 判断奇数还是偶数【c语言】
  15. VirtualBox 安装 Ubuntu Server 出现 Kernel Panic - not syncing: Attempted to kill the idle task 问题
  16. Introduction to Graph Neural Network(图神经网络概论)翻译:Chapter2:Basic of Math and Graph
  17. 第三章:进程线程模型
  18. BAT大厂面试题以及答案(一)
  19. 【计算机科学】【2004.06】动态环境中的移动机器人导航
  20. 第二篇 USB2.0协议简述(包-事务-传输)

热门文章

  1. R语言文本分析《三国演义》
  2. 安科瑞5G基站智慧用电解决方案(安科瑞-须静燕)
  3. 计算机中继承的英语作文,传统文化的继承To Inherit the Tradition(高中英语作文)
  4. 微软绑定office攻占云服务市场
  5. LeetCode——山羊拉丁文算法源码
  6. 软件版本号讲解:什么是Alpha, Beta, RC,Release
  7. 火锅点餐系统(非常适合新人上手的项目)
  8. SQL数据库服务器搬迁注意事项
  9. 计算机world excel,(World和Excel在使用上有什么区别)excel表格制作
  10. 自媒体文章可以多平台分发吗?