美文网首页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