ANR 问题一般解决思路

本文案例主要源于项目上实际遇到的问题,希望通过梳理之后能够对ANR问题能够快速定位,减少排查时间,同时在遇到棘手问题,能够更加从容。

先说下三种常见类型
1:KeyDispatchTimeout(谷歌default 5s,MTK平台上是8s) --主要类型
按键或触摸事件在特定时间内无响应
2:BroadcastTimeout(10s)
BroadcastReceiver在特定时间内无法处理完成
3:ServiceTimeout(20s) --小概率类型
Service在特定的时间内无法处理完成

一般解决步骤

Step1:日志获取&注意事项

获取日志有一点需要注意,发生ANR后,不要选择结束进程,因为这样AMS会kill掉该进程,有些信息会打印不出来(比如MTK平台上会生成db.XX.ANR,写入到aee_exp文件夹下需要时间),最好是ANR发生后等两三分钟左右,再获取日志

一般需要data/anr下生成的trace文件以及手机系统日志(一般只需要mobile文件夹)
以MTK为例,需要如下日志信息:
1.aee_exp文件夹(MTK日志目录下,发生ANR会生成)
2.MTK目录下的mobilelog文件夹

这里的aee_exp文件夹一般都是需要的, 对DB进行dump解析,得到ANR发生时场景信息,比如主线程callstack,CPU,memory等,在分析问题根因时很关键。

Step2:日志分析一般步骤

Step2.1 确认时间点(非必需)
mobilelog文件夹下的events_log,搜索关键字"am_anr",这一步用于确认ANR时间点,可以搜索到类似如下信息

04-29 10:00:57.240 1267 1341 I am_anr : [0,6073,com.android.dialer,952745541,Input dispatching timed out

比如上面这行表示ANR类型为Input dispatching timed out, 这种anr的原因的是在viewrootimpl分发事件时,并没有找到focuswindow导致的

这一步确认时间点在:10:00:57,进程号:6073

Step2: 查看ANR时的CPU以及IO率(可选)
这一步一般来说能基本定位是什么造成了ANR,是IO高还是CPU高,如两者都不是,需进入第三步trace日志分析环节 查看mobilelog文件夹下的main_log,搜索关键字"ANR in",可以看到当时的CPU以及IO率,这一个环节一般来讲主要是看发生ANR时的CPU使用情况,CPU是否吃紧,

还有需要注意iowait的占有率,如果占比比较高,则排查的方向要倾向与读取文件操作有关的信息,可以看trace日志中有没有一些读取文件或者操作SD卡的动作

Step3:分析ANR时的堆栈(必需,最重要的环节)

ANR发生后会在data/anr下生成trace.txt,这份trace务必要与moile日志匹配,一般来讲直接先看tid=1的堆栈即对应主线程,因为ANR都是主线程执行超时导致
关于trace日志的分析是ANR问题分析最重要的一个环节,下面将列出平时项目中遇到的ANR案例类型

ANR常见类型归纳
1.主线程Binder调用等待超时
比如下面的这段

1_binder等待超时.png

很明显当时在做Binder通信,并没有waiting to lock等代表死锁的字样,那么说明这个案例即有可能是在等Binder对端响应,我们知道Binder通信对于发起方来说是默认是阻塞等待响应,只有有了返回结果后才会继续执行下去,当然了可以给接口设置oneway声明,这样的话binder请求就是异步请求,这里不多说

所以,如上这个案例中需要找到对端是哪个进程,这个进程当时在做什么,这时候就需要找到anr文件夹下另外一个文件binderinfo,这里需要找到与我们发起方进程1461通信的是哪个进程

2_binder等待超时.png

可以看到是1666号这个进程,再回到trace中看下,这个进程当时在做什么

3_binder等待超时.png

可以看到当时对端在做消息的读取,也就是说这里出了问题,很明显这里我们无法修改,我们这个问题在于主线程执行了Binder请求,对端迟迟未返回便很容易出现这个问题,当前做法异步中执行

案例二:主线程等待锁
比如下面这个主线程的CallStack例子,可以看到如下信息:

4_主线程等待锁.png

这个案例中gallery的main thread在执行UploaderChimeraService的onDestroy方法时,需要lock 0x23f65d8b,但这个lock有被upload_periodic GCM Task 拿住,这个thread当前是在做连接网络的动作。从这段信息来看,很有可能与测试时手机连接的网络有关,当时连接的事google的网络,由于墙的原因,无法连接gms的相关server有关

还有一种情况就是死锁,即形成了头尾相连,互相等待的情况,对于这种问题以及上面案例的解决,一般会尝试将锁改为超时锁,比如lock的trylock,超时会自动释放锁,从而避免一直持有锁的情况发生

案例三:卡在IO上
这种情况一般是和文件操作相关,判断是否是这种情况,可以看mainlog中搜索关键字"ANR in",看这段信息的最下边,比如下面的信息
ANRManager: 100% TOTAL: 2% user + 2.1% kernel + 95% iowait + 0.1% softirq
很明显,IO占比很高,这个时候就需要查看trace日志看当时的callstack,或者在这段ANR点往前看0~4s,看看当时做的什么文件操作,这种场景有遇到过,常见解决方法是对耗时文件操作采取异步操作

案例四:主线程有耗时的动作
这种情况是ANR类型问题里遇到最多的,比如网络访问,访问数据库之类的,都很容易造成主线程堵塞,

这里以访问数据库来说,这类型引起的ANR,一般来讲看当时的CPU使用情况会发现user占比较高,看trace中主线程当时的信息会发现会有一些比如query像ContentProvider这种数据库的动作。这种情况下,还可以去看eventlog或者mainlog,在ANR发生前后打印出来的信息,比如访问数据库这种,在eventlog中搜索"am_anr",然后看前后片段,会发现发生ANR的这个进程有很多数据库相关的信息,说明在发生ANR前后主线程一直在忙于访问数据库,这类型的问题常见于图库,联系人,彩短信应用。

所以这种问题的解决,一般考虑的是异步解决,异步解决并不是简单的new一个线程,要根据业务场景以及频率来决定,Android常见的异步AsyncTask, IntentService, 线程池(官方四种或自定义), new thread等,一般来说不建议直接new thread

案例五:binder线程池被占满
系统对每个process最多分配15个binder线程,这个是谷歌的设计(/frameworks/native/libs/binder/ProcessState.cpp)
如果另一个process发送太多重复binder请求,那么就会导致接收端binder线程被占满,从而处理不了其它的binder请求

这时候请求端发起的请求就会阻塞等待了(未设置异步请求的前提下),这本身就是系统的一个限制,如果应用未按照系统的要求来实现对应逻辑,那么就会造成问题。
而系统端是不会(也不建议)通过修改系统行为来兼容应用逻辑,否则更容易造成其它根据系统需求正常编写的应用反而出现不可预料的问题。

判断Binder是否用完,可以在trace中搜索关键字"binder_f",如果搜索到则表示已经用完,然后就要找log其他地方看是谁一直在消耗binder或者是有死锁发生

之前有遇到过压力测试手电筒应用,出现BInder线程池被占满情况,解决的思路就是降低极短时间内大量Binder请求的发生,修复的手法是发送BInder请求的函数中做时间差过滤,限定在500ms内最多执行一次

案例六:JE或者NE导致ANR
这种场景有遇到过,ANR前出现频繁NE,NE所在的进程与ANR的进程有交互,在解决了NE后,ANR也不复存在,对于这类在ANR前有JE或者NE,一般思路是先解决JE或NE,因为JE/NE发生时会去dump一大堆异常信息,本身也会加重CPU loading,修改完异常后再来看ANR是否还存在,如果还存在,那么就看trace 堆栈,如果不存在,则可以基本判定是JE或NE导致

案例七:只存在于Monkey测试下
有些问题是只有在Monkey环境下才能跑出来,平时的user版本用户使用是不会出现的,这种问题的话就没有改动的意义。

比如下面这个例子:

ActivityManager: Not finishing activity because controller resumed
03-18 07:25:50.901 810 870 I am_anr : [0,25443,android.process.media,1086897733,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的原因是Contoller将resume的操作给拦截了, 导致Focus不过去, 从而导致ANR,User版本不会有Contoller, 所以不会出现这个 ANR. 所以这个 ANR 可以忽略.

ANR 问题一般解决思路相关推荐

  1. Android项目中多次操作SharedPreferences导致ANR场景的解决

    系列文章目录 Android项目中多次操作SharedPreferences导致ANR场景的解决 文章目录 系列文章目录 项目背景: 以定位来获取广告的方式为例: 所遇到的挑战: 解决问题的步骤: 问 ...

  2. 商品秒杀,防并发解决思路

    我们在做电商项目的时候,经常会遇到抢购秒杀的问题,综合来说主要是两个问题 一,高并发情况下对数据库产生的压力 二,如何避免超卖(库存< 0)的情况. 针对这两个问题来谈下解决思路 一,缓解数据库 ...

  3. 爬虫之常见的反爬手段和解决思路

    1 服务器反爬的原因 爬虫占总PV(PV是指页面的访问次数,每打开或刷新一次页面,就算做一个pv)比例较高,这样浪费钱(尤其是三月份爬虫). 三月份爬虫是个什么概念呢?每年的三月份我们会迎接一次爬虫高 ...

  4. nginx代理响应报文体不全解决思路

    问题说明 环境说明: centos 6.5 nginx 1.13.7 tomcat 8.5+ jdk 1.8 问题描述 本地访问测试机接口发生异常 curl访问结果: tomcat日志: 解决思路 开 ...

  5. c语言链表交换,求单链表的数据交换解决思路

    当前位置:我的异常网» C语言 » 求单链表的数据交换解决思路 求单链表的数据交换解决思路 www.myexceptions.net  网友分享于:2013-11-04  浏览:14次 求单链表的数据 ...

  6. 网站访问慢解决思路详细图解

    老男孩老师讲授网站访问慢解决思路思想,感谢21期的李同学图解呈现,此图才能与大家见面! 如果看着小,单击还原大图,可清晰查看!本图为亿图制作:亿图使用技巧: http://v.youku.com/v_ ...

  7. get_headers()请求https报错解决思路

    场景:项目中客户端上传文件到OSS后,返回给服务端一个OSS的文件对象名称. 服务端拿到文件对象名称后,需要通过OSSClient生成一个签名url,然后提供下载服务. 下载服务中,拿到URL后要去校 ...

  8. Exchange出站队列堵塞解决思路

    Exchange出站队列堵塞解决思路 2007-02-28 21:58:02 标签:Exchange [推送到技术圈] 版权声明:原创作品,谢绝转载!否则将追究法律责任. 点到为止,真诚希望对各位同行 ...

  9. Qt新建项目No valid kits found解决思路

    Qt新建项目No valid kits found解决思路 第一次用Qt Creator创建Project时,进入Kit Selection窗口后,会提示No Valid kits found. Pl ...

最新文章

  1. 【建站系列教程】2.2、fiddler手机抓包教程
  2. JavaScript 开发者数量暴涨、C# 超越 PHP,揭晓全球开发最新趋势!
  3. 用正则表达式去除行首行尾空格
  4. JAVA8之lambda表达式
  5. gitbook新版本 build命令导出的html不能跳转?
  6. 关于STM32 IAP
  7. 【Clickhouse】Too many partitions for single INSERT block (more than 100)
  8. Oracle密码过期处理
  9. Java进程中的堆和栈_对于JVM,你就只知道堆和栈吗?
  10. 在内核中使用线程与skb队列发送数据
  11. 玩转C语言Socket网络编程
  12. SkyWalking8.7源码解析(三):静态方法插桩、构造器和实例方法插桩、插件拦截器加载流程、JDK类库插件工作原理
  13. 韩咏梅:幸福只需要七分饱(转自新加坡联合早报)
  14. IPLC专线使用心得,速度惊人!
  15. 沙盘游戏让我变成“诗人”
  16. 软件使用小技巧-Linux疑难杂症
  17. Kubernetes源码下载以及go mod依赖解决
  18. 小学数学与计算机整合课优质教案,小学数学优质课教案《长方形的面积》(通用5篇)...
  19. 调节e18-d80nk的测量距离_教程 | GOM数字图像处理三维光学测量系统(ARAMIS) 的设备标定方法...
  20. kubernetes 曲线救国式下载 kubeadm 1.21 相关镜像

热门文章

  1. MFC 获取其他窗口的Edit文本和单击Button
  2. 计算机组成原理4位ALU运算器设计,计算机组成原理课程设计-alu设计和4位锁存器设计.doc...
  3. mysql建立修改表存储过程_MySQL数据库创建、表的创建、存储过程、触发器
  4. 服务端设置忽略更新_react服务端渲染: cookie如何透传给后端,后端如何设置cookie...
  5. 创龙28377d历程_C28x系列的28069、28377D的PWM使用经验
  6. 朴素贝叶斯网络进行邮件分类
  7. 浮点类型float double 以及BigDecimal
  8. P1396 营救(并查集+二分)
  9. centos-7部署docker
  10. mac配置jenkins遇到的问题及解决办法