Android之ANR分析

 

一 ANR简介

ANR和crash的区别:ANR不一定是由于程序的异常错误导致的,一般是应用处理长时间没有响应导致主线程不能处理下一件事情

ANR(Application not responding)即应用无响应,应用发生anr的几种类型

1 KeyDispatchTimeout:最常见的anr类型是对输入事件5s内无响应,比如按键或触摸事件在此时间内无响应

2 BroadcastTime:BroadcastReceiver在指定事件(原生系统默认是10s)内无法处理完成,并且没有结束执行onReceive

3 ServiceTimeout:这种类型在Android应用中出现的概率很小,是指service在特定时间(原生系统是20s)内无法处理完成

引起anr的根本原因总体来说有以下两种:

1)应用程序自身逻辑有缺陷,或者在某些异常场景触发了此缺陷,如主线程堵塞、死循环等导致

2)由于Android设备其他进程的CPU占用高,导致当前应用进程无法抢占到CPU时间片

二 ANR分析

在Android系统上,如果发生ANR,Logcat会产生对于的日志和一个trace文件,主要是分析这两个信息

导出命令:adb pull /data/anr/traces.txt D:\temp

 

1)Logcat分析

 

关键信息如下:

ANR IN:发生anr的具体类

PID:发生ANR的进程,系统在此时会生成trace文件,当前的时间点也是发生anr的具体时间,以及生成trace文件的时间

Reson:当前anr的类型以及导致anr的原因

CPU usage:CPU的使用情况,在日志CPU usage有两个时间点,第一个是发生anr前的CPU使用情况,第二个是发生anr后的CPU使用情况

从logcat中除了能看出在哪个类发生anr以及anr的类型,具体的原因主要还是要看CPU的使用情况,如果CPU使用量很少,说明主线程可能阻塞,如果IOwait很高,说明anr有可能是由于主线程进行耗时的I/O操作造成的

2)trace分析

trace文件保存在/data/anr/trace.txt

这个日志很容易定位是onClick事件中超时导致

场景二:

在Activity的onCreate中开启了一个线程,在线程中执行testANR(),而testANR()和initView()都被加了同一个锁,为了百分之百让testANR()先获得锁,特意在执行initView()之前让主线程休眠了10ms,这样一来initView()肯定会因为等待testANR()所持有的锁而被同步住,这样就产生了一个稍微复杂些的ANR。这个ANR是很参考意义的,这样的代码很容易在实际开发中出现,尤其是当调用关系比较复杂时,这个时候分析ANR日志就显得异常重要了。下面的代码中虽然已经将耗时操作放在线程中了,按道理就不会出现ANR了,但是仍然要注意子线程和主线程抢占同步锁的情况

 

首先看主线程,如下所示。可以看得出主线程在initView方法中正在等待一个锁<0x422a0120>,这个锁的类型是一个MainActivity对象,并且这个锁已经被线程id为11(即tid=11)的线程持有了,因此需要再看一下线程11的情况。

 

tid是11的线程就是“Thread-13248”,就是它持有了主线程所需的锁,可以看出“Thread-13248”正在sleep, sleep的原因是MainActivity的57行,即testANR方法。这个时候可以发现testANR方法和主线程的initView方法都加了synchronized关键字,表明它们在竞争同一个锁,即当前Activity的对象锁,这样一来ANR的原因就明确了,接着就可以修改代码了 

 

 

Android studio分析trace的工具:Analyze Stacktrace

Analyze Stacktrace使用方法

1 在Android studio工具栏中,选择Analyze ->Analyze Stacktrace,打开Analyze Stacktrace工具窗口

2 将trace.txt中的内容复制到窗口,单击Normalize按钮,生成Thread Dump列表

3 如果某个线程被标红,说明此线程被堵塞了,然后在右边的详细信息中查看堵塞的具体原因

注:部分anr是由于多个线程之前的同步锁导致,在使用Analyze Stacktrace分析时,可以再详情页面查看是在等待哪个线程,再定位到对应的线程

 

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值