上帝说要有ANR,因而Bugly就有了ANR上报。那么ANR到底是什么?java
近期很是多童鞋问起精神哥ANR的问题,那么此次就来聊一下,鸡爪怎么泡才好吃。噢不,是怎样高速定位ANR。数据库
ANR是什么
简单说,一般就是App执行的时候,duang~卡住了。怎么搞都动不了。安全
当卡住超过必定时间。Android系统以为这就是一次“ANR(Application Not Responding)”。网络
详细说。在下面状况发生时,会发生ANR(可能在不一样ROM 中时间有所更改):app
用户的输入在5s内没被App响应。函数
BroadcastReceiver的onReceiver()超过10s;性能
Service中各生命周期函数运行超过20s。动画
ANR必须死
用户在App的绝大部分操做,都需要有App的主动回应。比方按下button以后button样式的改变、下拉滚动栏内容的移动、载入资源时的菊花转转转,它们都是“操做-反馈”配对的模式。对于咱们手机上最多见的触摸操做。0.1s的响应延迟已经有很是明显的卡顿感了。而对于常见的ANR。用户至少要等5s以上!ui
发生了ANR,每每会弹出对话框,问用户是继续等待仍是直接关掉:spa
相信差点儿所有Android手机用户都见过这个然并卵的ANR对话框,但大部分普通用户根本不知道这个对话框在讲什么,并且每每也仅仅有关闭App。
漫长的等待就给我看这个?从用户的体验看,就是心中一万仅仅草泥马奔腾起来撞火车的感觉。可见ANR对于应用的影响并不亚于Crash。
通常来讲,界面相对越不“流畅”的App(说明UI线程耗时操做多)越easy发生ANR(一个输入事件在某个设备A上4秒有了反馈。并不意味着它在其它设备B上是安全的)。
ANR事实上就是界面卡顿的极端状况。反过来,仅仅要经过合理的方案消灭了App出现的ANR,每每也同一时候会使App展现界面表现会更加顺滑流畅。
一些典型的ANR 问题场景
这里举几个easy发生ANR的场景:
1)最多见的错误,UI线程等待其余线程释放某个锁,致使UI线程没法处理用户输入。
2)游戏中每帧动画都进行了比較耗时的大量计算,致使CPU忙只是来;
3)Web应用中。网络状态不稳定。而界面在等待网络数据;
4)UI线程中进行了一些磁盘IO(包含数据库、SD卡等等)的操做。在个别设备上因为硬件损坏等缘由堵塞住了;
5)手机被其它App占用着CPU。本身获取不到足够的CPU 时间片,纯属误伤。
经过ANR 日志定位问题
当ANR发生时。咱们每每经过Logcat和traces文件(文件夹/data/anr/)的相关信息输出去定位问题。主要包括下面几方面:
1)基本信息,包含进程名、进程号、包名、系统build号、ANR 类型等等;
2)CPU使用信息。包含活跃进程的CPU 平均占用率、IO状况等等。
3)线程堆栈信息。所属进程包含发生ANR的进程、其父进程、近期有活动的3个进程等等。
这里举个简单的样例(实际上因为各App所处环境各异,可能出现各类各样复杂的ANR状况)当App执行卡住,弹出ANR对话框。查看Logcat输出:
ActivityManager: ANR in com.tencent.bugly.demo (com.tencent.bugly.demo/.MainActivity) ActivityManager: PID: 18617 ActivityManager: Reason: Input dispatching timed out (Waiting because the touched window has not finished processing the input events that were previously delivered to it.) ActivityManager: Load: 18.42 / 18.09 / 18.29 ActivityManager: CPU usage from 5924ms to 475ms ago: ActivityManager: 93% 18617/com.tencent.bugly.demo: 93% user + 0% kernel / faults: 75 minor …… ActivityManager: CPU usage from 2906ms to 3429ms later: ActivityManager: 96% 18617/com.tencent.bugly.demo: 96% user + 0% kernel …… ActivityManager: 55% TOTAL: 51% user + 3.8% kernel
分析一下,从Logcat可以获得下面信息:
com.tencent.bugly.demo这个App的MainActivity发生了ANR,进程号18617;
ANR缘由:用户输入超时。
ANR发生前、后一段时间分别附在状况:在ANR发生先后,CPU有90+%耗费在这个demo上,说明很是多是这个demo自身性能引发的。
接下来再看traces文件确认:
----- pid 18617 at xxxx ----- Cmd line: com.tencent.bugly.demo JNI: CheckJNI is off; workarounds are off; pins=0; globals=272 (plus 2 weak) DALVIK THREADS: "main" prio=5 tid=1 SUSPENDED | group="main" sCount=1 dsCount=0 obj=0x415e4e58 self=0x415d3028 | sysTid=18617 nice=0 sched=0/0 cgrp=apps handle=1074372948 | state=S schedstat=( 38588000572 591063492 5767 ) utm=3846 stm=12 core=0 at com.tencent.bugly.demo.MainActivity$3.doCalc(MainActivity.java:~38) at com.tencent.bugly.demo.MainActivity$3.onClick(MainActivity.java:33) ……
分析一下,traces文件里包括下面信息:
一、进程号:18617;包名:com.tencent.bugly.demo。
二、发生ANR时,main线程被挂起(也多是其它等待状态,比方TIMED_WAIT);
三、线程的几个重要參数:
group:线程组名称“main”;
sCount:Suspended个数“1”。
obj:线程的Java对象地址。
self:线程的Native对象地址;
sysTid:线程号(这里主线程的线程号=进程号)“18617”。
四、详细堆栈:从堆栈可以很是清晰看出是doCalc()方法出的问题,由onClick触发。
综合以上分析。问题还原为:com.tencent.bugly.demo这个App的MainActivity中有个耗时的doCalc方法在跑。没法响应用户的触摸或按键输入。OK。接下来在代码里找问题就行了。
怎样解决ANR
固然是尽量下降UI线程的耗时操做。以及BroadcastReceiver、Service生命周期中的标准回调方法啦。
Android官方文档建议:
1)使用AsyncTask类,可以很是方便地实现子线程耗时操做与UI更新;
2)对于BroadcastReceiver的耗时操做。建议放到Service中运行。
3)对于自建的Thread,可以经过Handler使之与UI 线程通讯(这里需要注意的是。Thread默认优先级和UI线程是同样的,建议设置通常线程优先级为Process.THREAD_PRIORITY_BACKGROUND)。
这些方案你们应该都知道。只是仍不免有大量的ANR是写代码时忽略了,在測试时没发生,终于在用户的手机上出现的。回忆一下是否是都经历过用户会反馈“App卡死没反应了”。但开发GG客服MM们却又因为缺乏日志或没法复现而一筹莫展?所以要修复ANR。首先是要能发现用户ANR了。并且能知道是哪段代码致使ANR了,这样才干谈修复。
为了帮助广大开发人员解决这一难题,腾讯Bugly针对iOS的卡顿及Android的ANR提供监測服务即将上线,协助开发人员轻松定位问题。