Android如何分析排查ANR

在Android开发中,当程序发生异常时会抛出异常信息,先说下三种常见类型:

  • 列表内容KeyDispatchTimeout(谷歌default 5s,MTK平台上是8s) –主要类型
    按键或触摸事件在特定时间内无响应
  • BroadcastTimeout(10s)
    BroadcastReceiver在特定时间内无法处理完成
  • ServiceTimeout(20s) –小概率类型
    Service在特定的时间内无法处理完成

一些典型的ANR 问题场景

1)最常见错误,UI线程等待其它线程释放某个锁,导致UI线程无法处理用户输入;

2)游戏中每帧动画都进行了比较耗时的大量计算,导致CPU忙不过来;

3)Web应用中,网络状态不稳定,而界面在等待网络数据;

4)UI线程中进行了一些磁盘IO(包括数据库、SD卡等等)的操作,在个别设备上因为硬件损坏等原因阻塞住了;

5)手机被其他App占用着CPU,自己获取不到足够的CPU 时间片,纯属误伤。

排查分析的思路:

1、通过ANR 日志定位问题

当ANR发生时,我们往往通过Logcat和traces文件(目录/data/anr/)的相关信息输出去定位问题。主要包含以下几方面:

1)基本信息,包括进程名、进程号、包名、系统build号、ANR 类型等等;

2)CPU使用信息,包括活跃进程的CPU 平均占用率、IO情况等等;

3)线程堆栈信息,所属进程包括发生ANR的进程、其父进程、最近有活动的3个进程等等。

1.1首先通过Log来获取异常信息

android系统会自动帮我们生成一个log日志输出文件,在data/system/dropbox/下,真机测试需要root权限,模拟器在DDMS下可以查看。

用这种方法,出现问题,根本不需要断点调试 , 直接定位到问题,屡试不爽 。
从LOG可以看出ANR的类型,CPU的使用情况,

一般在如下几种情况会产生log 。

1,程序异常退出 , uncaused exception
2,程序强制关闭 ,Force Closed (简称FC)
3,程序无响应 , Application No Response (简称ANR) , 顺便,一般主线程超过5秒么有处理就会ANR

步骤:

1.打开log文件 , 由于是ANR错误,因此搜索”ANR ” , 为何要加空格呢,你加上和去掉比较一下就知道了 。 可以屏蔽掉不少保存到anr.log文件的无效信息

定位到关键的事件信息如下:

01-15 16:49:02.433 E/ActivityManager( 2466): ANR in com.android.mms (com.android.mms/.ui.SlideshowActivity)
01-15 16:49:02.433 E/ActivityManager( 2466): Reason: keyDispatchingTimedOut
01-15 16:49:02.433 E/ActivityManager( 2466): Load: 0.6 / 0.61 / 0.42
01-15 16:49:02.433 E/ActivityManager( 2466): CPU usage from 1337225ms to 57ms ago:
01-15 16:49:02.433 E/ActivityManager( 2466):   sensorserver_ya: 8% = 0% user + 8% kernel / faults: 40 minor
......
01-15 16:49:02.433 E/ActivityManager( 2466):  -com.android.mms: 0% = 0% user + 0% kernel
01-15 16:49:02.433 E/ActivityManager( 2466):  -flush-179:8: 0% = 0% user + 0% kernel
01-15 16:49:02.433 E/ActivityManager( 2466): TOTAL: 25% = 10% user + 14% kernel + 0% iowait + 0% irq + 0% softirq
01-15 16:49:02.436 I/        ( 2466): dumpmesg > "/data/log/dumpstate_app_anr.log"

我们用自然语言来描述一下日志,

01-15 16:49:02.433 E/ActivityManager( 2466): ANR in com.android.mms (com.android.mms/.ui.SlideshowActivity)

翻译:在16:49分2秒433毫秒的时候 ActivityManager (进程号为2466) 发生了如下错误:com.android.mms包下面的.ui.SlideshowActivity 无响应 。

01-15 16:49:02.433 E/ActivityManager( 2466): Reason: keyDispatchingTimedOut

翻译:原因 , keyDispatchingTimeOut - 按键分配超时

01-15 16:49:02.433 E/ActivityManager( 2466): Load: 0.6 / 0.61 / 0.42

翻译:5分钟,10分钟,15分钟内的平均负载分别为:0.6 , 0.61 , 0.42

我们大概知道问题是什么了,问题是在点击按钮某时候可能处理不过来按钮事件,导致超时无响应 。但我们不能准确的知道到底问题在哪儿 , 只是猜测 ,比如这个应用程序中,多个IO操作的地方都在主线程中,可能引起问题,但不好判断到底是哪个 ,所以我们目前掌握的信息还不够 。
于是我们再分析虚拟机信息 ,搜索“Dalvik Thread”关键词,快速定位到本应用程序的虚拟机信息日志

1.2通过分析trace文件得到ANR信息(真机导出,模拟机在DDMS下查看)

如果ANR发生,对应的应用会收到SIGQUIT异常终止信号,dalvik虚拟机就会自动在/data/anr/目录下生成trace.txt文件,将异常信息写入到traces文件中,系统会记录异常的位置、CPU和内存当时的使用情况,通过查看日志基本就能判断问题所在。

接下来用adb shell命令导出该文件,通过shell命令就可以了。

adb pull /data/anr/traces.txt d:/ =》意思是将手机上的traces.txt导出到电脑的d目录下
或者
1、adb shell
2、cat /data/anr/xxx >/mnt/sdcard/yy/zz.txt
3、exit
4、adb pull /mnt/sdcard/yy/zz.txt d: ,即可将文件导出到了d盘。

在发生ANR时,

步骤:
1. 找到ANR关键字(大写匹配)
2. 向上查找timeout关键字,这个时候能找到ANR的原因,如: Application do too much work in main thread 等。
3. 查看trace 文件找出出现的最终原因。

测试过程发现ANR的现状

1、在平常测试中,ANR基本测试不到,因为ANR基本发生在垃圾设备中,弱网络,频繁操作。
2、问题不必现,即使看到了问题,定位麻烦:要去data/anr.txt 文件里面查找。必须root,没有对应关系,分析复杂,导出文件就必须依赖手机零距离。
由于anr问题不必现,因此引入以下ANR检测工具,当anr问题出现时,自动dump手机中的日志信息如trace文件、堆栈信息
基本原理

检测到UI主线程卡顿时间超过设定的时间,如4s,即dump trace文件以及堆栈信息,同时抛出异常,收集信息,根据这些文件信息即可定位到发生anr的原因

1.3在源代码中插入ANR检测工具(BlockCanary、StrictMode)

根据提示找到来找到原因,
更多参考:blockcanary,BlockCanary解析,strictMode

1.4使用第三方SDK输出Crach信息到后台服务器:

如腾讯bugly 和umeng

你可能感兴趣的:(Android如何分析排查ANR)