Android 开发高手课 01 | 崩溃优化(上)关于“崩溃”那些事儿

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

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 配置里增加如下配置
javascript 复制代码
 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 版本

相关推荐
Dingdangr3 小时前
Android中的Intent的作用
android
技术无疆3 小时前
快速开发与维护:探索 AndroidAnnotations
android·java·android studio·android-studio·androidx·代码注入
GEEKVIP4 小时前
Android 恢复挑战和解决方案:如何从 Android 设备恢复删除的文件
android·笔记·安全·macos·智能手机·电脑·笔记本电脑
Jouzzy10 小时前
【Android安全】Ubuntu 16.04安装GDB和GEF
android·ubuntu·gdb
极客先躯11 小时前
java和kotlin 可以同时运行吗
android·java·开发语言·kotlin·同时运行
茜茜西西CeCe13 小时前
移动技术开发:登录注册界面
java·gitee·gradle·android studio·安卓·移动技术开发·原生安卓开发
Good_tea_h13 小时前
Android中的单例模式
android·单例模式
黑狼传说15 小时前
前端项目优化:极致最优 vs 相对最优 —— 深入探索与实践
前端·性能优化
Lill_bin17 小时前
Lua编程语言简介与应用
开发语言·数据库·缓存·设计模式·性能优化·lua
计算机源码社18 小时前
分享一个基于微信小程序的居家养老服务小程序 养老服务预约安卓app uniapp(源码、调试、LW、开题、PPT)
android·微信小程序·uni-app·毕业设计项目·毕业设计源码·计算机课程设计·计算机毕业设计开题