本文微信公众号「安卓小煜」首发

1. 布景

最近重读了 Android 开发高手课,记录一下阅读的一些笔记。
包括有些之前课后作业完成不了的,这次也都同时完成了。

假如想看课后作业的,能够直接定位到最后一节,前面的都是原文的一个汇总。

2. 溃散的分类

  1. Java 溃散:在 Java 代码中,呈现了未捕获的反常,导致程序反常退出。
  2. Native 溃散:一般都是由于在 Native 代码中拜访非法地址,也可能是地址对齐呈现了问题,或许发生了程序自动 abort,这些都会发生相应的 signal 信号,导致程序反常退出。

2.1 Native 溃散的捕获流程

  • 编译端。编译 C/C++ 代码时,需要将带符号信息的文件保留下来。
  • 客户端。捕获到溃散时候,将收集到尽可能多的有用信息写入日志文件,然后挑选合适的时机上传到服务器
  • 服务端。读取客户端上报的日志文件,寻找合适的符号文件,生成可读的 C/C++ 调用栈。

2.2 Native 溃散捕获的难点

最中心的是怎样样保证客户端在各种极端状况下仍然能够生成溃散日志

  • 状况一:文件句柄泄漏,导致创立日志文件失利,怎样办?
    提早申请文件句柄 fd 预留,防止呈现这种状况
  • 状况二:由于栈溢出了,导致日志生成失利,怎样办?
    运用常见的 signalstack,预留部分堆空间
  • 状况三:整个堆的内存都耗尽了,导致日志生成失利,怎样办?
    Breadpad 做法是从头封装了 Linux Syscall Support,来防止直接调用 libc。
  • 状况四:堆破坏或二次溃散导致日志生成失利,怎样办?
    从原进程 fork 出子进程。某些特殊状况下,还可能从子进程 fork 出孙进程。

2.3 挑选合适的溃散服务

对于很多中小型公司来说,能够挑选一些第三方的服务。

从产品化和社区保护来说,引荐 Bugly。
从技术深度跟捕获能力来说,引荐啄木鸟平台。

3. 一些衡量指标

3.1 如何客观地衡量溃散

假如想评价溃散形成的用户影响范围,我们会先去看 UV 溃散率。

UV 溃散率 = 发生溃散的 UV / 登录 UV

3.2 如何客观地衡量稳定性

  • 怎样去发现运用中的 ANR 反常呢?
    1. 运用 FileObserver 监听 /data/anr/traces.txt 的变化
    2. 监控音讯队列的运行时刻

    这两个办法都无法精确的发现 ANR

  • UV 反常率 = 发生反常退出或溃散的 UV / 登录 UV

4. 课后作业

机器环境
OS version: macOS Monterey 12.5
AS version: Android Studio Electric Eel | 2022.1.1 Patch 2

仓库地址:Chapter01

重点说一下在依照 README 操作的过程中遇到的问题。

  • 问题一

NDK is missing a “platforms” directory.
If you are using NDK, verify the ndk.dir is set to a valid NDK directory. It is currently set to /Users/zhanzengyu/Library/Android/sdk/ndk-bundle.
If you are not using NDK, unset the NDK variable from ANDROID_NDK_HOME or local.properties to remove this warning.

解法一(引荐):装备 NDK 版别,这边运用 16.1.4479499 是能够的
解法二:在 ndk-bundle 下面创立platforms 空目录

  • 问题二

ABIs [arm64-v8a] are not supported for platform. Supported ABIs are [armeabi-v7a, x86].

解法一(引荐):装备 NDK 版别,这边运用 16.1.4479499 是能够的
解法二:删去 breakpad-build 和 sample 下 abiFilters 里边的 “arm64-v8a”

  • 问题三

x86 模拟器点击 crash 按钮确实闪退了,可是没有生成 dmp 文件

解法一:依照 GitHub 说的方法装备(PS:注意,假如 NDK 版别不对,会报错:GCC is no longer supported)

  1. 将 ndk 切换到 16b,下载地址:github.com/android/ndk…
  2. 在 Androidstudio 里设置 ndk 途径为ndk-16b的途径
  3. 在 sample 和 breakpad-build 的 build.gradle 装备里增加如下装备
 externalNativeBuild {
            cmake {
                cppFlags "-std=c++11"
                arguments "-DANDROID_TOOLCHAIN=gcc"
            }
        }

解法二:运用真机

  • 问题四

dyld[51346]: Symbol not found: (__ZTTNSt7__cxx1118basic_stringstreamIcSt11char_traitsIcESaIcEEE)
Referenced from: ‘/Users/zhanzengyu/Desktop/zengyu/project/github/Chapter01/tools/mac/minidump_stackwalk’
Expected in: ‘/usr/lib/libstdc++.6.dylib’
[1] 51346 abort ./098877a7-142f-4668-8784c3b0-fc8eaaef.dmp > crashLog.txt

解决方案:运用 AndroidStudio 里边自带的 minidump_stackwalk
位置在:/Applications/Android Studio.app/Contents/plugins/android-ndk/resources/lldb/bin/minidump_stackwalk

总结来说,最重要的是要装备正确的 NDK 版别