ANR简介
ANR是“应用无响应”(Application not responding)的简称,ANR发生时用户输入行为无响应、前台会展示ANR弹窗。
知识储备
线程与进程
线程是基本的cpu执行的单元,程序执行流的最小单元,不拥有系统资源,与其他线程共享资源。
进程是系统进行资源和调度的一个独立单位,拥有系统资源。
死锁
多线程中出现资源争用现象,导致相互阻塞。
Binder
Android底层的一种进程间通信方式。Android中四大组件的通信底层都依赖于Binder IPC。
ANR原因
产生ANR的直接原因是组件执行超时,而组件产生超时的原因是应用的主进程执行了耗时任务或者被阻塞。
主线程IO
在输入事件中执行文件读写操作(耗时超过5S),重复点击两次触发ANR
log直接输出ANR的原因。
内存紧张
cpu总共被使用99%
定位问题
严格模式
StrictMode是一个可以检测线程中耗时行为的工具,当检测到问题时回以弹窗或者日志提示开发者关注问题。
StrictMode 最常用于捕获应用程序主线程上的意外磁盘或网络访问,其中接收 UI 操作并发生动画。使磁盘和网络操作远离主线程可以使应用程序更加流畅、响应速度更快。
在application或者activity的onCreat中添加如下代码,StrictMode支持探测代码中网络请求、文件读写等耗时操作
- setThreadPolicy:设置应检测当前线程上的哪些操作的策略以及哪些惩罚。
- setVmPolicy:设置应检测 VM 进程(在任何线程上)中的哪些操作的策略及惩罚。
StrictMode 不是一种安全机制,不能保证找到所有磁盘或网络访问。虽然它在进行 Binder 调用时会跨进程边界传播其状态,但它最终仍然是一种尽力而为的机制。需要注意的是来自 JNI 调用的磁盘或网络访问不一定会触发它
Android Profiler
developer.android.com/studio/prof…
Trace文件
导出anr文件命令
- adb bugreport
- adb pull data/anr/traces.txt ~/your path/traces.txt
经验总结
- 绝大部份情况都是因为主线程执行任务耗时而导致的,先看Trace文件的主线程中正在执行的任务,再根据mapping文件映射到我们的代码中,再定位具体耗时的那一行代码。
- 系统服务超时会导致ANR,我们可以看下trace中是否包含BinderProxy.transactNative关键字
- 还有一些trace上的堆栈上看不出什么问题,先看下cpu使用情况,我们需要关注cpu使用情况的最后一行TOTAl use,如下图cpu总共被使用99%,这时候发上ANR也不足为奇了。