赞
踩
ANR类型
KeyDispatchTimeout
(常见。Input的超时机制与其他的不同,对于input来说即便某次事件执行时间超过timeout时长,只要用户后续在没有再生成输入事件,则不会触发ANR)
input事件在5S内没有处理完成发生了ANR。
logcat日志关键字:Input event dispatching timed out
BroadcastTimeout
前台Broadcast:onReceiver在10S内没有处理完成发生ANR。
后台Broadcast:onReceiver在60s内没有处理完成发生ANR。
解释:根据发送广播sendBroadcast(Intent intent)中的intent的flags是否包含FLAG_RECEIVER_FOREGROUND来决定把该广播是放入前台广播队列或者后台广播队列,前台广播队列的超时为10s,后台广播队列的超时为60s,默认情况下广播是放入后台广播队列,除非指明加上FLAG_RECEIVER_FOREGROUND标识。
后台广播比前台广播拥有更长的超时阈值,同时在广播分发过程遇到后台service的启动(mDelayBehindServices)会延迟分发广播,等待service的完成,因为等待service而导致的广播ANR会被忽略掉;后台广播属于后台进程调度组,而前台广播属于前台进程调度组。简而言之,后台广播更不容易发生ANR,同时执行的速度也会更慢。
另外,只有串行处理的广播才有超时机制,因为接收者是串行处理的,前一个receiver处理慢,会影响后一个receiver;并行广播通过一个循环一次性向所有的receiver分发广播事件,所以不存在彼此影响的问题,则没有广播超时。
logcat日志关键字:Timeout of broadcast BroadcastRecord
ServiceTimeout
前台Service:onCreate,onStart,onBind等生命周期在20s内没有处理完成发生ANR。
后台Service:onCreate,onStart,onBind等生命周期在200s内没有处理完成发生ANR
logcat日志关键字:Timeout executing service
解释:进程调度组大体可分为TOP、前台、后台,进程优先级(Adj)和进程调度组(SCHED_GROUP)算法较为复杂,其对应关系可粗略理解为Adj等于0的进程属于Top进程组,Adj等于100或者200的进程属于前台进程组,Adj大于200的进程属于后台进程组。关于Adj的含义见下表,简单来说就是Adj>200的进程对用户来说基本是无感知,主要是做一些后台工作,故后台服务拥有更长的超时阈值,同时后台服务属于后台进程调度组,相比前台服务属于前台进程调度组,分配更少的CPU时间片。
ContentProviderTimeout
ContentProvider 在10S内没有处理完成发生ANR。
logcat日志关键字:timeout publishing content providers
尽量避免anr
1:主线程频繁进行耗时的IO操作:如数据库读写
2:多线程操作的死锁,主线程被block;held by
3:主线程被Binder 对端block;
4:System Server中WatchDog出现ANR;
5:service binder的连接达到上线无法和和System Server通信
6:系统资源已耗尽(管道、CPU、IO)
后台ANR相比前台ANR,只抓取发生无响应进程的trace,也不会收集CPU信息,并且会在后台直接杀掉该无响应的进程,不会弹框提示用户。
查找anr 用 bugly第三方 内部实现类似fileObserver
通过logcat日志,traces文件确认anr发生时间点
根据traces文件确定cpu的使用率
traces文件目录 是在/data/anr/traces.txt
分析主线程状态和其他线程状态
是io堵塞或者cpu耗尽等分析问题
日志重要信息
ANR时间:07-20 15:36:36.472
进程pid:1480
进程名:com.xxxx.moblie
ANR类型:KeyDispatchTimeout
cpu未耗尽一般是死锁anr 搜索(held by或者waiting to lock)信息
iowait很高 说明anr有可能是主线程在进行io操作
内存使用情况、cup使用情况
观察main线程出现什么事情
anr采集的2中方式
1、fileObserver 代表监控莫个目录/文件 状态发生变化 创建 删除(5.0后会被selinux挡住)
自己实现通过继承fileObserver 监听 data/anr/ 该目录需要root权限取出,但是可以通过copy拿到(猜想未尝试)
Android系统在此基础上封装了一个FileObserver类来方便使用Inotify机制。FileObserver是一个抽象类,需要定义子类实现该类的onEvent抽象方法,当被监控的文件或者目录发生变更事件时,将回调FileObserver的onEvent()函数来处理文件或目录的变更事件
2、watchdog
继承Thread 单例。在run方法中。 经过以下步骤
1、设置为后台线程
2、一直while(true) 循环
3、新建一个ANRChecker,Runnable对象。调用自己的schedule()方法中设置
mCompleted=false,记录开始时间。通过
new Handler(Looper.getMainLooper()).postAtFrontOfQueue(this);
把自己立即发送Message到队列的最前面
4、wait(设置的时间)wait 函数极小概率会提前唤醒。一般需要在加一个while进行时间到0判断
5、等待结束后判断 mCompleted是否为false,如果未被修改。表明有可能出现anr,下载堆栈信息。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。