美文网首页
崩溃优化(下)应用崩溃了,你应该如何去分析?

崩溃优化(下)应用崩溃了,你应该如何去分析?

作者: YoungTr | 来源:发表于2019-03-20 13:51 被阅读0次

    崩溃现场

    1. 崩溃信息

    从崩溃的基本信息,可以对崩溃有初步的判断。

    • 进程名、线程名。崩溃的进程是前台进程还是后台进程,崩溃是不是发生在 UI 线程。
    • 崩溃堆栈和类型。崩溃是属于 Java 崩溃、Native 崩溃,还是 ANR。特别需要看崩溃堆栈的栈顶,看具体崩溃在系统代码,还是我们自己的代码里面。
        AndroidRuntime: FATAL EXCEPTION: MyThread
        Process: com.simple.carsh, PID: 6825
        java.lang.ArithmeticException: divide by zero
            at com.simple.crash.TouchActivity$1.run(TouchActivity.java:33)
    

    2. 系统信息

    • Logcat。包括应用、系统运行日志。其中系统的 event logcat 会记录 App 运行的一些基本情况,记录在文件 /system/etc/event-log-tags 中

    • 机型、系统、厂商、CPU、ABI、Linux 版本等;

    • 设备状态:是否 root、是否模拟器;

    3. 内存信息

    OOM 、 ANR、虚拟内存耗尽等,很多崩溃都跟内存有直接关系。

    • 系统剩余内存。关于系统内存状态,可以直接读取文件 /proc/meminfo 当系统可用内存很小(低于 MemTotal 的 10%)时,OOM、大量 GC、系统频繁自杀拉起等问题都非常容易出现。
    // /proc/meminfo
    
    MemTotal:        1550948 kB
    MemFree:          465832 kB
    Buffers:           25008 kB
    Cached:           764404 kB
    SwapCached:            0 kB
    Active:           480312 kB
    Inactive:         550552 kB
    Active(anon):     241468 kB
    Inactive(anon):    12292 kB
    Active(file):     238844 kB
    Inactive(file):   538260 kB
    Unevictable:           0 kB
    Mlocked:               0 kB
    HighTotal:        663432 kB
    HighFree:          13024 kB
    LowTotal:         887516 kB
    LowFree:          452808 kB
    SwapTotal:             0 kB
    SwapFree:              0 kB
    Dirty:                 0 kB
    Writeback:             0 kB
    AnonPages:        241436 kB
    Mapped:           188572 kB
    Shmem:             12324 kB
    Slab:              21936 kB
    SReclaimable:      10864 kB
    SUnreclaim:        11072 kB
    KernelStack:        4056 kB
    PageTables:         6132 kB
    NFS_Unstable:          0 kB
    Bounce:                0 kB
    WritebackTmp:          0 kB
    CommitLimit:      775472 kB
    Committed_AS:   18331812 kB
    VmallocTotal:     122880 kB
    VmallocUsed:       26120 kB
    VmallocChunk:      31652 kB
    HugePages_Total:       0
    HugePages_Free:        0
    HugePages_Rsvd:        0
    HugePages_Surp:        0
    Hugepagesize:       4096 kB
    DirectMap4k:       16376 kB
    DirectMap4M:      892928 kB
    
    
    • 应用使用内存。包括 Java 内存、RSS(Resident Set Size)、PSS(Proportional Set Size), 我们可以得出应用本身内存的占用大小和分布。PSS 和 RSS 通过 /proc/self/smap 计算,可以进一步得到例如 apk、dex、so 等详细的分类统计。
    • 虚拟内存。虚拟内存可以通过 /proc/self/status 得到,通过 /proc/self/maps 文件可以得到具体的分布情况,很多类似 OOM、tgkill 等问题都是虚拟内存不足导致的。
    
    //  /proc/self/status 
    
    Name:     com.sample.name   // 进程名
    FDSize:   800               // 当前进程申请的文件句柄个数
    VmPeak:   3004628 kB        // 当前进程的虚拟内存峰值大小
    VmSize:   2997032 kB        // 当前进程的虚拟内存大小
    Threads:  600               // 当前进程包含的线程个数
    

    4. 资源信息

    • 文件句柄 fd 。文件句柄的限制可以通过 /proc/self/limits 获得,一般单个进程允许打开的最大文件句柄个数为 1024。但是如果文件句柄超过 800 个就比较危险,需要将所有的 fd 以及对应的文件名输出到日志中,进一步排查是否出现了有文件或者线程的泄漏。

    • 线程数。当前线程数大小可以通过上面 status 文件得到,一个线程可能占 2MB 的虚拟内存,过多的线程会对虚拟内存和文件句柄带来压力。

    • JNI。使用 JNI 时,如果不注意很容易出现引用失效,引用爆表等一些崩溃。

    5. 应用信息

    • 崩溃场景。崩溃发生在哪个 Activity 或 Fragment,发生在哪个业务中。
    • 关键操作路径。

    崩溃分析

    第一步:确认重点

    1. 确认严重程度。优先解决 Top 崩溃或者对业务有重大影响的崩溃。
    2. 崩溃的基本信息。确定崩溃的类型已经异常描述,对崩溃有大致的判断。
    • Java 崩溃。Java 崩溃比较明显,比如 NullPointerException 是空指针;

    • Native 崩溃。需要观察 signal、code、fault addr 等内容,已经崩溃时 Java 的堆栈。崩溃信号介绍

    • ANR。先看看主线程的堆栈,是否是因为锁等待导致。接着看看 ANR 日志中 iowait、CUP、GC、system server 等信息,进一步确认是 I/O 问题,或者是 CPU 竞争问题,还是由于大量 GC 导致卡死。

    1. LogCat。从 LogCat 中我们可以看到当时系统的一些行为跟手机状态,例如出现 ANR 时,会有 “am_arn”; App 被杀时,会有“am_kill” 。

    2. 各个资源情况。结合崩溃信息,看看是不是跟“内存信息”有关,是不是跟“资源信息”有关,比如物理内存不足,虚拟内存不足,还是文件句柄 fb 泄漏了。

    内存与线程相关的信息都需要特别注意,很多崩溃都是它们使用不当造成的。

    第二步:查找共性

    共性问题例如是不是因为安装了 Xposed,是不是只出现在 x86 的手机等

    第三步:尝试复现

    1. 查找功能的原因。通过上面的共性归类,先看看是某个系统版本的问题,还是某个厂商特定 ROM 的问题。

    2. 尝试规避。查看可疑代码调用,是否使用了不恰当的 API,是否可以切换其他的实现方式规避。

    3. Hook 解决。

    相关文章

      网友评论

          本文标题:崩溃优化(下)应用崩溃了,你应该如何去分析?

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