ANR----以及如何定位是前端问题还是后台问题?

ANR----以及如何定位是前端问题还是后台问题?

一、ANR说明和原因
1.1 简介
ANR全称:Application Not Responding,也就是应用程序无响应。

1.2 原因
Android系统中,ActivityManagerService(简称AMS)和WindowManagerService(简称WMS)会检测App的响应时间,如果App在特定时间无法相应屏幕触摸或键盘输入时间,或者特定事件没有处理完毕,就会出现ANR。

以下四个条件都可以造成ANR发生:

InputDispatching Timeout:5秒内无法响应屏幕触摸事件或键盘输入事件
BroadcastQueue Timeout :在执行前台广播(BroadcastReceiver)的onReceive()函数时10秒没有处理完成,后台为60秒。
Service Timeout :前台服务20秒内,后台服务在200秒内没有执行完毕。
ContentProvider Timeout :ContentProvider的publish在10s内没进行完。
1.3 避免
尽量避免在主线程(UI线程)中作耗时操作。

那么耗时操作就放在子线程中。
关于多线程可以参考:Android多线程:理解和简单使用总结

二、ANR分析办法
2.1 ANR重现
这里使用的是号称Google亲儿子的Google Pixel xl(Android 8.0系统)做的测试,生成一个按钮跳转到ANRTestActivity,在后者的onCreate()中主线程休眠20秒:

在进入ANRTestActivity后黑屏一段时间,大概有七八秒,终于弹出了ANR异常。
Google Pixel xl ANR.png
2.2 ANR分析办法一:Log
刚才产生ANR后,看下Log:

可以看到logcat清晰地记录了ANR发生的时间,以及线程的tid和一句话概括原因:WaitingInMainSignalCatcherLoop,大概意思为主线程等待异常。
最后一句The application may be doing too much work on its main thread.告知可能在主线程做了太多的工作。
2.3 ANR分析办法二:traces.txt
刚才的log有第二句Wrote stack traces to ‘/data/anr/traces.txt’,说明ANR异常已经输出到traces.txt文件,使用adb命令把这个文件从手机里导出来:

cd到adb.exe所在的目录,也就是Android SDK的platform-tools目录,例如:
cd D:\Android\AndroidSdk\platform-tools
此外,除了Windows的cmd以外,还可以使用AndroidStudio的Terminal来输入adb命令。

到指定目录后执行以下adb命令导出traces.txt文件:
adb pull /data/anr/traces.txt
traces.txt默认会被导出到Android SDK的\platform-tools目录。一般来说traces.txt文件记录的东西会比较多,分析的时候需要有针对性地去找相关记录。
在文件中使用 ctrl + F 查找包名可以快速定位相关代码。

进程id和包名:
造成ANR的原因:Sleeping
造成ANR的具体行数:ANRT
特别注意:产生新的ANR,原来的 traces.txt 文件会被覆盖。

2.4 ANR分析办法三:Java线程调用分析
通过JDK提供的命令可以帮助分析和调试Java应用,命令为:

jstack {pid}
其中pid可以通过jps命令获得,jps命令会列出当前系统中运行的所有Java虚拟机进程,比如

具体分析参考:Android应用ANR分析 四.1节

2.5 ANR分析办法四:DDMS分析ANR问题
使用DDMS——Update Threads工具
阅读Update Threads的输出

三、造成ANR的原因及解决办法
上面例子只是由于简单的主线程耗时操作造成的ANR,造成ANR的原因还有很多:

主线程阻塞或主线程数据读取
解决办法:避免死锁的出现,使用子线程来处理耗时操作或阻塞任务。尽量避免在主线程query provider、不要滥用SharePreferenceS

CPU满负荷,I/O阻塞
解决办法:文件读写或数据库操作放在子线程异步操作。

内存不足
解决办法:AndroidManifest.xml文件中可以设置 android:largeHeap=“true”,以此增大App使用内存。不过不建议使用此法,从根本上防止内存泄漏,优化内存使用才是正道。

各大组件ANR
各大组件生命周期中也应避免耗时操作,注意BroadcastReciever的onRecieve()、后台Service和ContentProvider也不要执行太长时间的任务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值