IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> ANR分析 -> 正文阅读

[移动开发]ANR分析

1.什么是ANR
ANR即Application Not Responding,顾名思义就是应用程序无响应。在Android中,一般情况下,四大组件均是工作在主线程中的,Android中的Activity Manager和Window Manager会随时监控应用程序的响应情况,如果因为一些耗时操作(网络请求或者IO操作)造成主线程阻塞一定时间,那么系统就会显示ANR对话框提示用户对应的应用处于无响应状态。

2.为什么会发生ANR
一句话总结:主线程没有在规定的时间内,做完要做的事情,就会发生ANR。

Input事件超过5s没有被处理完
Service处理超时,前台20s,后台200s
BroadcastReceiver处理超时,前台10s,后台60s
ContentProvider执行超时10s
activity/broadcast/contentProvider超时(ActivityManagerService.java):
在这里插入图片描述

service超时(ActiveServices.java):

在这里插入图片描述

从发生的原因分:

主线程有耗时操作,如有复杂的layout布局,IO操作等;
被Binder对端block;
被子线程同步锁block;
Binder被占满导致主线程无法和SystemServer通信;
得不到系统资源(CPU/RAM/IO);
从进程的角度分:

问题出在当前进程;
主线程本身耗时,或者主线程的消息队列存在耗时操作;
主线程被本进程的其他子线程block;
问题出在远端进程(一般是binder call或socket等通信方式);

3.怎么解决ANR
3.1 导出trace文件
如果ANR发生,对应的应用会收到SIGQUIT异常终止信号,dalvik虚拟机就会自动在/data/anr/目录下生成trace.txt文件,这个文件记录了在发生ANR时刻系统各个线程的执行状态,通过adb pull命令将这个文件导出分析。

3.2 trace文件格式解析
导出trace文件后,可以看到类似于如下的文件内容:

说明了发生ANR的进程id、时间和进程名称。

  • tll:thread list lock
  • tsl:thread suspend lock
  • tscl:thread suspend count lock
  • ghl:gc heap lock
  • hwl:heap worker lock
  • hwll:heap worker list lock

说明了线程名称、线程的优先级、线程锁id和线程状态。

线程名称是启动线程的时候手动指明的,这里的main标识是主线程,是Android自动设定的一个线程名称,如果是自己手动创建的线程,一般会被命名成“Thread-xx”的格式,其中xx是线程id,它只增不减不会被复用;
注意这其中的tid不是线程的id,它是一个在Java虚拟机中用来实现线程锁的变量,随着线程的增减,这个变量的值是可能被复用的;

最后线程的状态还分为如下几种:

?

group:线程组名称;
sCount:此线程被挂起的次数;
dsCount:线程被调试器挂起的次数;当一个进程被调试后,sCount会重置为0,调试完毕后sCount会根据是否被正常挂起增长,但是dsCount不会被重置为0,所以dsCount也可以用来判断这个线程是否被调试过;
obj:表示这个线程的Java对象的地址;
self:表示这个线程本身的地址;

线程的调度信息:

  • sysTid:Linux下的内核线程id;
  • nice:线程的调度优先级;
  • sched:分别标志了线程的调度策略和优先级;
  • cgrp:调度属组;
  • handle:线程的处理函数地址;

线程当前上下文信息:

state:调度状态;
schedstat:从 /proc/[pid]/task/[tid]/schedstat读出,三个值分别表示线程在cpu上执行的时间、线程的等待时间和线程执行的时间片长度,有的android内核版本不支持这项信息,得到的三个值都是0;
utm:线程用户态下使用的时间值(单位是jiffies);
stm:内核态下的调度时间值;
core:最后执行这个线程的cpu核的序号;
3.3 trace文件分析

trace文件顶部的线程一般是ANR的元凶

这是一个简单的方法,但是大部分情况下都适用,可以通过这个方法来快速判断是否是自己的应用造成了本次ANR。但是,并不是trace文件包含的应用就一定是造成ANR的帮凶,应用出现在trace文件中,只能说明出现ANR的时候这个应用进程还活着,trace文件的顶部则是触发ANR的应用信息。因此,如果你的应用出现在了trace文件的顶部,那么很有可能是因为你的应用造成了ANR,否则是你的应用造成ANR的可能性不大,但是具体是不是还需要进一步分析。

注意死锁和等待

虽然说ANR一般情况是由于让主线程做了很多耗时的操作,但是死锁或者主线程等待也是ANR高发的原因。
案例一

虽然应用com.hhhh.core出现在了trace文件中,但是在ANR的时候它在通过IPCThread在进行进程间通信,可查看远端进程binder的block。

案例二?

?这种情况说明ANR发生于com.android.example应用中,而且指明了ANR发生时代码的执行位置,很有可能是我们应用程序的问题,之后就需要通过这个trace文件指明的路径来对代码进行排查。

案例三

binder_3正处于monitor状态,也就是它在等待一个synchronized块或者方法,但是目前这个monitor正在被tid=12的线程持有,所以造成了此线程被阻塞。

mAccountInfoFile->accounts.xml文件地址:data/system/sync
accounts.xml文件乱码,读取时加了同步锁导致anr

系统耗时分析方案
系统做了一些耗时分析的操作,Log里面有体现。

binder_sample
功能说明:监控每个进程的主线程的binder transaction的耗时情况, 当超过阈值时,则输出相应的目标调用信息,默认1000ms打开。
log格式:52004 binder_sample (descriptor|3),(method_num|1|5),(time|1|3),(blocking_package|3),(sample_percent|1|6)
log实例:2754 2754 I binder_sample: [android.app.IActivityManager,35,2900,android.process.media,5]
log解释:执行android.app.IActivityManager接口时,所对应方法code =35(即STOP_SERVICE_TRANSACTION),花费了2900ms,block在package为 android.process.media的地方。
dvm_lock_sample
功能说明:当某个线程等待lock的时间blocked超过阈值,则输出当前的持锁状态 ;
log格式: 20003 dvm_lock_sample (process|3),(main|1|5),(thread|3),(time|1|3),(file|3),(line|1|5),(ownerfile|3),(ownerline|1|5),(sample_percent|1|6)
log实例:dvm_lock_sample: [system_server,1,Binder_9,1500,ActivityManagerService.java,6403,-,1448,0]
log解释:当system_server进程中的Binder_9线程执行到ActivityManagerService.java的6403行代码时,一直在等待AMS锁, 但该锁被同一文件的1448行代码所持有, 从而导致Binder_9线程被阻塞1500ms.


ANR小结

搜索关键字:

【last ANR】
【InputDispatcher】
【wm_on_】
【ActivityManager: ANR in】

分析过程:

搜索关键字【VM TRACES AT LAST ANR】找到ANR的trace文件(该文件内容其实就在下面几行),通过关键字【“main”】查看主线程调用栈,如果调用栈中有我们APP包名调用的方法就能直接定位到是哪里的问题了
搜索关键字【ActivityManager: ANR in】,下一行【Reason】可以直接看到ANR产生的原因
然后看看【CPU usage】部分,看看哪个APP占用cpu比例最高,如果某个APP占用CPU超过100%,那很大概率是该APP引起的;如果CPU占用率很低,那可能是主线程阻塞了。
【TOTAL:】部分可以看出占用CUP的哪一类操作,比如【iowait】是指正在等待IO操作;
如果【Reason:】显示” Input dispatching timed out”,那么可以搜索【InputDispatcher】以及【wm_on_】关键字,根据ANR发生时间找到该时间前后打印的Log,比如【Reason: Input dispatching timed out (ActivityRecord{c88403a u0 com.android.settings/.homepage.SettingsHomepageActivity t78} does not have a focused window)】,经过排查就是该Activity在ANR发生之前就已经stop了,导致没有focused window去处理该input事件


ANR的常见类型

ANR一般有三种类型:

1:KeyDispatchTimeout(5 seconds) --主要类型

按键或触摸事件在特定时间内无响应

2:BroadcastTimeout(10 seconds)

BroadcastReceiver在特定时间内无法处理完成

3:ServiceTimeout(20 seconds) --小概率类型

Service在特定的时间内无法处理完成

三:KeyDispatchTimeout

Akey or touch event was not dispatched within the specified time(按键或触摸事件在特定时间内无响应)

具体的超时时间的定义在framework下的

ActivityManagerService.java

//How long we wait until we timeout on key dispatching.

staticfinal int KEY_DISPATCHING_TIMEOUT = 5*1000

四:为什么会超时呢?

超时时间的计数一般是从按键分发给app开始。超时的原因一般有两种:

(1)当前的事件没有机会得到处理(即UI线程正在处理前一个事件,没有及时的完成或者looper被某种原因阻塞住了)

(2)当前的事件正在处理,但没有及时完成

五:如何避免KeyDispatchTimeout

1:UI线程尽量只做跟UI相关的工作

2:耗时的工作(比如数据库操作,I/O,连接网络或者别的有可能阻碍UI线程的操作)把它放入单独的线程处理

3:尽量用Handler来处理UIthread和别的thread之间的交互

六:UI线程

说了那么多的UI线程,那么哪些属于UI线程呢?

UI线程主要包括如下:

  1. Activity:onCreate(), onResume(), onDestroy(), onKeyDown(), onClick(),etc

  2. AsyncTask: onPreExecute(), onProgressUpdate(), onPostExecute(), onCancel,etc

  3. Mainthread handler: handleMessage(), post*(runnable r), etc

  4. other

参考网址

android ANR产生原因和解决办法【转】_第八个猴子的博客-CSDN博客

Android 系统稳定性 - ANR 解析_飞翔凡人的博客-CSDN博客

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-05-08 08:15:26  更:2022-05-08 08:17:29 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 23:35:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码