• ANR一般性分析方法


    Android项目的ANR问题经常让开发者困扰。究其原因,有些ANR问题很难定位。
    若ANR和普通crash一样,打出耗时操作的调用栈,那么想办法修复就好了。
    最近项目中的ANR问题较为严重,相信每个快速膨胀的app都会经历这个时刻,总结一些经验供大家参考。
     
    ANR原因
    ANR是耗时操作造成。
    若有A/B/C事件串行执行于UI线程,当C事件发生ANR时,说明A->B->C太耗时了,并不能确定耗时操作在哪个具体事件上。
     
    ANR基本定位
    ANR的有用信息,我们需要在trace文件中获取。
    trace文件路径:dataanr races_packageName.txt
    在trace文件中,我们能够看到如下信息
    DALVIK THREAD(14)表明trace文件中收集了14个线程的信息与调用栈。
    下面的"main"指的是主线程,我们分析"main"所在的片段即可定位ANR。
    图中所示,调用栈指向了com.puff.test.MainActivity.onResume方法,这就是ANR发生的原因,调用到onResume方法时,超时了!
     
    ANR定位不准
    当跟随调用栈查看onResume方法时,我们发现唯一的操作便是耗时操作
    onResume阻塞了2s,造成了ANR。但是Activity的超时需要5s未响应,看来ANR的原因不仅仅是onResume造成的。
    我们继续跟踪onResume之前调用的onCreate与onStart
      
    所以根据trace文件定位ANR未必能准确,trace只给出了造成ANR的直接原因,间接原因仍然需要分析。
     
    ANR辅助定位——BlockCanary
    通过trace文件能够确定发生ANR的位置,但只是压死骆驼的最后一根稻草。
    而BlockCanary工具却能统计到过程中所有耗时操作(耗时阈值由自己设置)。
     
    原理比较简单,通过替换Looper的Printer达到计算msg处理的耗时。
    同时也提供了一些很有帮助的参数,譬如总耗时与线程耗时,可用内存等。
    具体内容可详见 BlockCanary
     
    ANR辅助定位——埋点
    通过trace文件与BlockCanary工具基本上可以定位耗时操作了,不过仍然有些情况会让人困扰。
    若query(*,*)是耗时操作,在onStart中调用了多次,造成了onResume产生ANR,那么虽然能定位query是耗时操作,却不能确定是哪个操作真正耗时。
    方法内多次调用同一耗时操作,那么就果断埋点吧!
    通过埋点统计操作用时,即可更准确定位耗时操作。
     
    多次采样确定ANR耗时操作
    ANR不好复现,耗时操作的耗时也不稳定,通过多次采样来确定耗时操作似乎已经是通用方案了。
    若是层级较深或复杂操作才能触发耗时操作的,推荐使用iTestin工具进行自动化测试。
    iTestin工具的功能非常丰富,常用的操作都可以通过iTestin来模拟进行,更多的内容就阅读文档吧http://i.testin.cn/
    若是比较简单的操作,可以直接通过adb的shell命令进行自动化测试了。
    譬如上例中onResume经常发生ANR,那么多次启动并关闭就可以多次采样了。
    adb shell am start com.puff.test/com.puff.test.MainActivity
    adb shell am kill com.puff.test
    便可执行启动与关闭页面,我们再循环执行一定次数就可以采样了。
  • 相关阅读:
    Hibernate一对多OnetoMany
    80端口被占用 PID = 4解决办法
    Devexpress Barmanager设置
    通过C# 打开一个应用程序
    C#DataTable操作
    C# Winform 双屏显示
    Dev gridview 调整字体大小
    在静态页面html中跳转传值
    js 求两个日期之间相差天数
    jQuery 知识积累
  • 原文地址:https://www.cnblogs.com/puff/p/5535436.html
Copyright © 2020-2023  润新知