Android 崩溃分析 方法论

文章目录

    • Android 崩溃分析 方法论
      • 一. 崩溃现场信息收集
        • 1. 崩溃信息
        • 2. 系统信息
        • 3. 内存信息
        • 4. 资源信息
        • 5. 应用信息
      • 二. 崩溃信息分析
        • 1. 确定严重程度
        • 2. 确定崩溃信息
        • 3. 汇集资源使用情况
        • 4. 尝试复现
      • 三. 崩溃问题修复
        • 1. 查找可能的所有原因
        • 2. 尝试规避
        • 3. Hook解决

一. 崩溃现场信息收集

1. 崩溃信息

  • 执行信息: 进程名称, 线程名称
  • 执行状态: 前台进程, 后台进程, UI进程
  • 崩溃类型: Java崩溃, Native崩溃, ANR, OOM
  • 堆栈状态: Native堆栈, Java堆栈, 主线程堆栈

2. 系统信息

  • 设备信息: 机型, 系统版本, 厂商, CPU, ABI, Linux版本, 网络, 电量, 磁盘等

  • Logcat: 查询 /system/etc/event-log-tags文件, 文件权限为 -rw-r–r--

    system logcat:10-25 17:13:47.788 21430 21430 D dalvikvm: Trying to load lib ... event logcat:10-25 17:13:47.788 21430 21430 I am_on_resume_called: 生命周期10-25 17:13:47.788 21430 21430 I am_low_memory: 系统内存不足10-25 17:13:47.788 21430 21430 I am_destroy_activity: 销毁 Activty10-25 17:13:47.888 21430 21430 I am_anr: ANR 以及原因10-25 17:13:47.888 21430 21430 I am_kill: APP 被杀以及原因

3. 内存信息

  • 系统内存: 系统剩余内存, 系统本身内存, 可以读取 /proc/meminfo查看

  • 应用内存: RSS(Resident Set Size), PSS(Proportional Set Size), Java内存, Java栈, Native内存, Native栈

  • 虚拟内存: App虚拟内存整体通过 /proc/pid/status查看, App虚拟内存细节, 通过 /proc/pid/maps查看

    // 文件/proc/pid/statusName:     com.sample.name   // 进程名FDSize:   800               // 当前进程申请的文件句柄个数VmPeak:   3004628 kB        // 当前进程的虚拟内存峰值大小VmSize:   2997032 kB        // 当前进程的虚拟内存大小Threads:  600               // 当前进程包含的线程个数

4. 资源信息

  • 文件句柄: 通过查询 /proc/pid/limits查询, 默认一个进程可打开最大句柄为1024, 所有句柄可在 /proc/pid/fd目录下查询

    // 目录/proc/pid/fdlrwx------ 1 u0_a999 u0_a999 64 2019-05-31 11:32 0 -> /dev/nulllrwx------ 1 u0_a999 u0_a999 64 2019-05-31 11:32 1 -> /dev/nulllrwx------ 1 u0_a999 u0_a999 64 2019-05-31 11:32 2 -> /dev/null
  • 线程数量: 通过查询 /proc/pid/status可以得到当前线程数量, 一个线程可能拥有2MB的虚拟内存

  • JNI: 注意引用失效, 引用报表等问题, 通过 DumpReferenceTables统计引用表, 进一步分析内存泄露

5. 应用信息

  • 崩溃场景: 所在Activity或Fragment, 具体业务
  • 操作步骤: 记录记录用户操作步骤, 便于开发环境重现
  • 状态信息: 根据崩溃所处的业务模块, 收集相关联的模块状态信息

二. 崩溃信息分析

1. 确定严重程度

严重程度可分为 致命, 严重, 一般, 提示, 根据严重程度分出优先级; 还要注意迭代情况, 如果下一个版本就取消了该功能, 就可以放低该问题优先级

2. 确定崩溃信息

确定崩溃类型, 如 Java崩溃, Native崩溃, ANR, OOM

  • ANR: 查看主线程堆栈, 是否是因为锁造成; 继续查看 /data/anr/traces.txt寻找 iowait, CPU, GC, system_server等信息
  • Java崩溃: 可以直接查看栈信息进行排查
  • Native崩溃: 注意singal、code、fault addr等内容, 以及Java堆栈信息, Native异常排查参考
信号量 Value 描述 例子
SIGABRT 6 进程发现错误或者主动调用abort(); 很多C的库函数中, 如果发现异常会调用abort, 如strlen
SIGBUS 7, 10 不存在的物理地址, 硬件有误 更多的是因为硬件或者系统引起的
SIGFPE 8 浮点数运算错误 如除0操作, 整形溢出
SIGILL 4 非法指令 损坏的可执行文件或者代码区损坏
SIGSEGV 11 段地址错误 空指针, 访问不存在的地址空间, 访问内核区, 写只读空间, 栈溢出, 数组越界, 野指针
SIGPIPE 13 管道错误, 往没有reader的管道中写 Linux中的socket, 如果断掉了继续写

3. 汇集资源使用情况

分析App内存, 磁盘, 网络, fd等资源信息, 汇总机型, 厂商, 系统, ABI等不同维度的信息

4. 尝试复现

不管是否已经找到原因, 都应该尝试用户的步骤进行重现, 这样既可以得到最新的问题资源信息, 也可以得到问题出现的大概位置和原因

三. 崩溃问题修复

1. 查找可能的所有原因

找到问题出现的点, 进一步分析为什么出现这种问题, 有没有其他位置也有类似的问题; 通过用户的操作步骤可以在其他模块进行尝试发掘新的问题

2. 尝试规避

代码中是否调用了不稳定的API, 或者调用方式不合规, 是否可以通过其他的方式达到相同的效果

3. Hook解决

有些问题是系统问题, 低版本可能出现频率大, 高版本不存在, 这时我们可以查看高版本代码如何写的, 利用Hook, 按照高版本的方式进行规避

更多相关文章

  1. 南青信息查询 for Android客户端
  2. Android进程
  3. 【Android 内存优化】Android 工程中使用 libjpeg-turbo 压缩图
  4. Android之rild进程启动源码分析
  5. Android系统启动流程(1) —— 解析init进程启动过程
  6. 【随心笔录】Android多进程实现,一个APP多个进程

随机推荐

  1. Android(安卓)UI(1)Getting Started - Fi
  2. Android(安卓)UI 优化-使用theme 预加载
  3. android 让一个控件按钮居于底部的几种方
  4. 系出名门 Android(安卓)系列文章索引
  5. Android(安卓)UI之EditText注意点收集
  6. Android(安卓)TextView行间距解析
  7. Android学习笔记---第一天---布局
  8. Android各种资源引用的方法
  9. android:windowSoftInputMode属性使用
  10. Android中Intent对应的category列表大全