美文网首页Android收藏集
APP崩溃之BreakPad捕获异常

APP崩溃之BreakPad捕获异常

作者: PuHJ | 来源:发表于2019-07-20 14:21 被阅读16次

一、简介

在开发APP时一定会遇到程序异常退出的情况,有时相对于解决问题,发现定位问题更加的困难和重要。这里就需要一个功能强大的异常捕获框架——BreakPad

Android的崩溃大体可分为以下三种:

  • java层异常
  • Native层异常
  • ANR程序无响应:I/O、CPU或者大量GC导致的

对于以上三种情况,Native的异常捕获定位比较困难。需要对操作系统等底层有很深入的了解,以及一些极端情况的考虑(如日志生成失败导致的破坏了原来的崩溃现场)。才能制定一个优秀的异常捕获框架,但这也让BreakPad的代码量增加了。

二、window下使用BreakPad

1)、下载BreakPad源码

1、利用git等方式下载BreakPad源码,需要使用该编译源码生成工具,以及用到以上的JNI文件。
2、下载的头文件中会缺少一个文件夹,会导致配置编译的时候出现错误,这个需要手动的下载。这个可以在GitHub中下载
缺少的文件

2)、配置编译源码

1、环境准备

需要准备Linux系统和Make,我这里用的是ubantu-16-04-3版本、Make-4.1、XShell、共享工具

2、编译
  • 1、将下载的文件放置到Linux共享文件中(或用git下载到一个目录中)


    image.png
  • 2、配置编译
    利用XShell配置breakpad文件夹下面中的configure文件,并make编译。命令:./configure && make


    minidump_stackwalk

    完成后在processor目录下会有个minidump_stackwalk文件,之后会使用。

3)、使用Breakpad

下载的BreakPad源码会有JNI文件,利用该文件单独放置一个模块中,官方的例子中使用的是makefile,这里改用的是make编译。可以直接将GitHub中的breakpad下载使用。

public class BreakpadInit {
    static {
        System.loadLibrary("breakpad-core");
    }

    public static void initBreakpad(String path){
        initBreakpadNative(path);
    }

    private static native void initBreakpadNative(String path);
}

接下来使用breakpad就很简单了,直接在初始化BreakPad库的时候配置一个文件夹,该文件夹是存放之后生成的日志文件。

三、定位问题

  • 1、官方给出的Native奔溃例子如下:
#include <stdio.h>
#include <jni.h>


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

extern "C"
JNIEXPORT void JNICALL
Java_com_dodola_breakpad_MainActivity_crash(JNIEnv *env, jobject obj) {
    Crash();
}

奔溃后,取出生成的奔溃日志。我这里的日志名改成了t.dmp

  • 2、使用minidump_stackwalk
    在processor目录下,执行./minidump_stackwalk t.dmp > crash.txt
    之后会生成一个crash.txt的日志文件。
Operating system: Android
                  0.0.0 Linux 4.4.21-perf-g6679372 #1 SMP PREEMPT Tue Jan 23 00:40:47 CST 2018 aarch64
CPU: arm64
     8 CPUs

GPU: UNKNOWN

Crash reason:  SIGSEGV /SEGV_MAPERR
Crash address: 0x0
Process uptime: not available

Thread 0 (crashed)
 0  libcrash-lib.so + 0x5e0
     x0 = 0x0000007f7463e180    x1 = 0x0000007ffe09eb34
     x2 = 0x0000000000000000    x3 = 0x0000007f74696a00
     x4 = 0x0000007ffe09efa8    x5 = 0x0000007f58bbf506
     x6 = 0x00000000001b9ded    x7 = 0x0000000012c7cce8
     x8 = 0x0000000000000001    x9 = 0x0000000000000000
    x10 = 0x375abb98f10f9542   x11 = 0x0000000000000000
    x12 = 0x0000000000000000   x13 = 0x0000000000430000
    x14 = 0x0000000000000000   x15 = 0x0000007f745fc7d0
    x16 = 0x0000007f73024fe8   x17 = 0x0000007f730145cc
    x18 = 0x00000000000000af   x19 = 0x0000007f74696a00
    x20 = 0x0000007f7404d350   x21 = 0x0000007f74696a00
    x22 = 0x0000007ffe09eddc   x23 = 0x0000007f58bbf506
    x24 = 0x0000000000000004   x25 = 0x375abb98f10f9542
    x26 = 0x0000007f74696a98   x27 = 0x0000007f74690600
    x28 = 0x375abb98f10f9542    fp = 0x0000007ffe09eb10
     lr = 0x0000007f73014604    sp = 0x0000007ffe09eaf0
     pc = 0x0000007f730145e0
    Found by: given as instruction pointer in context
 1  libcrash-lib.so + 0x600
     fp = 0x0000007ffe09ebf8    lr = 0x0000007f58cfda94
     sp = 0x0000007ffe09eb20    pc = 0x0000007f73014604
    Found by: previous frame's frame pointer
 2  base.odex + 0x2f9a90
     fp = 0x0000007ffe09ecf0    lr = 0x0000007f7405af54
     sp = 0x0000007ffe09ec08    pc = 0x0000007f58cfda94
    Found by: previous frame's frame pointer

这里面有奔溃的位置:libcrash-lib.so + 0x5e0
使用的CPU架构:arm64

对于Crash Reason可以参考如下对应表:
Crash code对应表

对应上面的Native崩溃,可以看出崩溃的原因是“地址无效”导致的。

  • 3、使用addr2line
    在SDK中toolchain交叉编译工具链中,有个 aarch64-linux-android-addr2line.exe可执行文件进行符号解析,这样就可以将之前生成的crash.txt文件定位到哪一行的问题。

这里执行的命令:

aarch64-linux-android-addr2line.exe -f -C -e 
D:\F\project\self\github\AndroidAdvanceWithGeektime\Chapter01\sample\build\intermediates\transforms\mergeJniLibs\debug\0\lib\arm64-v8a\libcrash-lib.so 0x5e0

这里需要错误的so文件和crash.txt中报错对的偏移地址 0x5e0和addr2line.exe


addr2line

这里就可以定位到是这个so库中的Crash方法、第十行出现的问题。

相关文章

网友评论

    本文标题:APP崩溃之BreakPad捕获异常

    本文链接:https://www.haomeiwen.com/subject/ydpylctx.html