一、ANR类型
ANR,即“Application not responding”,在Android中,ManagerService会检测应用的响应时间,如果在约定时间内没有完成,那么系统就会判定应用ANR。
1、输入超时
05-28 11:25:00.420 ?1668 ?1713 E ActivityManager: PID: 23293
05-28 11:25:00.420 ?1668 ?1713 E ActivityManager: Reason: Input dispatching timed out (Waiting because no window has focus but there is a focused application that may eventually add a window when it finishes starting up.)
我们可以看到,当ANR类型是由输入超时引发时,我们通过日志可以检索到Input dispatching timed out,Android系统对输入的约定一般时前台8s,后台8s,但对于原生应用,可能会被限制在4-5s内
2、广播超时
广播根据Foreground类型,分为前台10s,后台60s,这里需要注意时间,后续分析日志信息的时候,我们需要根据这个信息去在对应的时间区间内寻找日志信息
Subject : broadcast of Intent/BROADCAST_TIMEOUT_MSG(xxxxxxxxxxxx)
3、Service超时
同样,Service超时也根据Foreground的类型分为前台10s,后台20s,其作用类似
下面展示一些 Service超时日志片段
。
Executing service packagename/serviceActivity(xxxxxxxxxxxx)
ANR问题如何分析
我们先通过ANR的一段日志来分析下各行时什么含义
// ANR内部日志截取
Process:com,taobao.taobao /发生ANR的进程名
Package:com.taobao.taobao /发生ANR的包名
Foreground:Yes /发生ANR的进程时在前台还是后台
Subject:Excuting service(xxxxxx) /发生ANR的类型
Lifetime:200s /从启动到应用ANR的生命周期
ANR问题如何定位
1、先从日志文件中确定发生ANR的进程、类型,去诶定进程是哪一个后,我们就能确定这个ANR是属于哪个应用的,第二部分析是哪种类型的ANR,就是前面讲到的时属于服务、广播还是输入事件触发的ANR,接下来,我们就需要根据我们前面分析的时间,来从ANR发生的时间往前推对应的时间片段,在这段时间区间内,就是我们需要好好去看的日志信息,以上就是ANR问题的分析步骤
几种常见的ANR分析思路
1、input等待触发ANR
//no focused window的ANR
09-09 17:49:58.482 1164 1347 W InputDispatcher: Waiting because no window has focus but ActivityRecord{94be3e0 u0 com.android.settings/.SubSettings t50} may eventually add a window when it finishes starting up. Will wait for 5000ms
...
09-09 17:49:58.482 1164 1347 W InputDispatcher: Still no focused window. Will drop the event in 4999ms
...
09-09 17:50:03.734 1164 9946 I am_anr : [0,1747,com.android.settings,952745541,Input dispatching timed out (ActivityRecord{94be3e0 u0 com.android.settings/.SubSettings t50} does not have a focused window)]
此类的ANR全称为:Waiting because no window has focus but ActivityRecord,当然还有其他的注解,我们需要注意的是,input时间发给某个应用时,需要先聚焦窗口,但是窗口又没有,input时间将会一直处于待机状态,就是处于等待发送的状态,直到指定的时间8s,这个时间段内的等待时正常的,超出了系统就不承认了。
所以我们理下思路,我们先要从systemAppAnr文件找到ANR发生时的activity,在applogcat中搜索windowmanager_windowchange,查看最后一次window切换,对比两者间的时间,看是否存在关联
2、等锁
下面展示一些 内联代码片
。
// waiting to lock;
// java.lang.Thread.State: BLOCKED (on object monitor)
at java.io.PrintStream.println(PrintStream.java:805)
- waiting to lock <0x0000000545f28398> (a java.io.PrintStream)
at org.apache.tomcat.util.log.SystemLogHandler.println(SystemLogHandler.java:264)
at com.wlw.action.UserAction.toLoginPage(UserAction.java:177)
我们从以上日志信息中可以看到,线程在等待一把被其他线程持有的锁,那么接下来的思路就是看看这把锁时被什么线程持有,在日志中找到这个线程后,再去分析为什么这个线程没有释放这把锁,可能也是再等待另一个线程的锁,这样,就会造成我们常说的死锁。最简单的处理方法就是去掉其中一个锁。
总结下ANR问题触发的几种原因
1、网络访问数据量过大
2、线程异常导致应用主线程卡死
3、IO流过大
4、数据库操作频繁
5、线程锁