ANR分析实例

目录

一、ANR出的问题原因

二、日志分析

2.1 CPU 负载

2.2 内存

2.3 堆栈信息

三、案例分析

3.1 主线程无卡顿,处于正常状态堆栈

3.2 主线程执行耗时操作

3.3 主线程被锁阻塞

3.4 CPU被抢占

3.5 内存紧张导致ANR

3.6 系统服务超时导致ANR

3.7 Input dispatching timed out


一、ANR出的问题原因

很多开发者认为,ANR就是耗时操作导致,全部是app应用层的问题。实际上,线上环境大部分ANR由系统原因导致。

应用层导致ANR(耗时操作)
1、函数阻塞:如死循环、主线程IO、处理大数据
2、锁出错:主线程等待子线程的锁
3、内存紧张:系统分配给一个应用的内存是有上限的,长期处于内存紧张,会导致频繁内存交换,进而导致应用的一些操作超时

系统导致ANR
1、CPU被抢占:一般来说,前台在玩游戏,可能会导致你的后台广播被抢占CPU
2、系统服务无法及时响应:比如获取系统联系人等,系统的服务都是Binder机制,服务能力也是有限的,有可能系统服务长时间不响应导致ANR
3、其他应用占用的大量内存

二、日志分析

2.1 CPU 负载



如上所示:

第一行:表明负载信息抓取在ANR发生之后的0~28360ms。同时也指明了ANR的时间点:2024-02-29 13:11:00.095

中间部分:各个进程占用的CPU的详细情况

最后一行:各个进程合计占用的CPU信息。

a. user:用户态,kernel:内核态
b. faults:内存缺页,minor——轻微的,major——重度,需要从磁盘拿数据
c. iowait:IO使用(等待)占比
d. irq:硬中断,softirq:软中断

iowait占比很高,意味着有很大可能,是io耗时导致ANR,具体进一步查看有没有进程faults major比较多。

单进程CPU的负载并不是以100%为上限,而是有几个核,就有百分之几百,如4核上限为400%。

2.2 内存



从含义可以得出结论:Free memory until OOME 的值很小的时候,已经处于内存紧张状态。应用可能是占用了过多内存。
ps:如果ANR时间点前后,日志里有打印onTrimMemory,也可以作为内存紧张的一个参考判断

2.3 堆栈信息


堆栈信息是最重要的一个信息,展示了ANR发生的进程当前所有线程的状态。



如上日志所示,本文截图了两个线程信息,一个是主线程main,它的状态是native。
另一个是OkHttp ConnectionPool,它的状态是TimeWaiting。众所周知,教科书上说线程状态有5种:新建、就绪、执行、阻塞、死亡。而Java中的线程状态有6种,6种状态都定义在:java.lang.Thread.State中


问题来了,上述main线程的native是什么状态,哪来的?
其实trace文件中的状态是是CPP代码中定义的状态,下面是一张对应关系表。

由此可知,main函数的native状态是正在执行JNI函数。堆栈信息是我们分析ANR的第一个重要的信息,一般来说:
main线程处于 BLOCK、WAITING、TIMEWAITING状态,那基本上是函数阻塞导致ANR;
如果main线程无异常,则应该排查CPU负载和内存环境。

三、案例分析


3.1 主线程无卡顿,处于正常状态堆栈



上述主线程堆栈就是一个很正常的空闲堆栈,表明主线程正在等待新的消息。
如果ANR日志里主线程是这样一个状态,那可能有两个原因:

遇到这种空闲堆栈,可以按照第2章的方法去分析CPU、内存的情况。其次可以关注抓取日志的时间和ANR发生的时间是否相隔过久,时间过久这个堆栈就没有分析意义了。

3.2 主线程执行耗时操作



上述日志表明,主线程正处于执行状态,看堆栈信息可知不是处于空闲状态,发生ANR是因为一处click监听函数里执行了耗时操作。

3.3 主线程被锁阻塞



这是一个典型的主线程被锁阻塞的例子;
其中等待的锁是<0x01aed1da>,这个锁的持有者是线程 3。进一步搜索 “tid=3” 找到线程3, 发现它正在TimeWating。
那么ANR的原因找到了:线程3持有了一把锁,并且自身长时间不释放,主线程等待这把锁发生超时。在线上环境中,常见因锁而ANR的场景是SharePreference写入。

3.4 CPU被抢占



如上日志,第二行是钉钉的进程,占据CPU高达543%,抢占了大部分CPU资源,因而导致发生ANR。

3.5 内存紧张导致ANR


如果有一份日志,CPU和堆栈都很正常(不贴出来了),仍旧发生ANR,考虑是内存紧张。
从CPU第一行信息可以发现,ANR的时间点是2020-10-31 22:38:58.468—CPU usage from 0ms to 21752ms later (2020-10-31 22:38:58.468 to 2020-10-31 22:39:20.220)
接着去logcat里搜索am_meminfo, 这个没有搜索到。再次搜索onTrimMemory,果然发现了很多条记录;


可以看出,在发生ANR的时间点前后,内存都处于紧张状态,level等级是80,查看Android API 文档;
可知80这个等级是很严重的,应用马上就要被杀死,被杀死的这个应用从名字可以看出来是桌面,连桌面都快要被杀死,那普通应用能好到哪里去呢?
一般来说,发生内存紧张,会导致多个应用发生ANR,所以在日志中如果发现有多个应用一起ANR了,可以初步判定,此ANR与你的应用无关。

3.6 系统服务超时导致ANR


系统服务超时一般会包含BinderProxy.transactNative关键字,请看如下日志:


以上可以看出来,是在从堆栈可以看出ANR:getExternalFilesDirs。

可以看出来是在AMS创建APP时出现的问题,因此可以给系统侧分析。

3.7 Input dispatching timed out


ANR部分日志信息:
PID: 32640
UID: 1110155
Input dispatching timed out (4e4035c com.aaa/com.aaa.home.MainActivity (server) is not responding. Waited 5001ms for MotionEvent(deviceId=-1, eventTime=85286596000000, source=0x00001002, displayId=0, action=DOWN, actionButton=0x00000000, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, classification=NONE, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, xCursorPosition=nan, yCursorPosition=nan, pointers=[0: (525.0, 957.0)]), policyFlags=0x6b000000)

CPU usage from 0ms to 31081ms later (2024-10-22 07:03:11.876 to 2024-10-22 07:03:42.956):

这个导致的原因有很多,这个问题无法从ANR日志里去分析,就需要从系统日志里去查找问题,这个报错的时间上,需要往前去找日志信息,从日志里可以找到关键的信息,如下

10-22 07:03:07.795 17729 17830 I InputDispatcher: Not sending touch event to 4e4035c com.aaa/com.aaa.home.MainActivity because it is paused

点击事件没有发送成功,说明这里就是发生问题的关键时间点,顺藤摸瓜,往上找一下有没有什么错误信息,
10-22 07:03:07.634 1015 15113 D EMS:ExceptionHandlerFactory: Get handler : STRICT_MODE
10-22 07:03:07.634 1015 15113 E JavaBinder: *** Uncaught remote exception! (Exceptions are not yet supported across processes.)
10-22 07:03:07.634 1015 15113 E JavaBinder: java.util.concurrent.RejectedExecutionException: Task c.a.a.a.u@4f72b0e rejected from java.util.concurrent.ThreadPoolExecutor@735f423[Running, pool size = 8, active threads = 8, queued tasks = 6, completed tasks = 19620]
10-22 07:03:07.634 1015 15113 E JavaBinder: at java.util.concurrent.ThreadPoolExecutorA b o r t P o l i c y . r e j e c t e d E x e c u t i o n ( T h r e a d P o o l E x e c u t o r . j a v a : 2086 ) 10 − 2207 : 03 : 07.634101515113 E J a v a B i n d e r : a t j a v a . u t i l . c o n c u r r e n t . T h r e a d P o o l E x e c u t o r . r e j e c t ( T h r e a d P o o l E x e c u t o r . j a v a : 848 ) 10 − 2207 : 03 : 07.634101515113 E J a v a B i n d e r : a t j a v a . u t i l . c o n c u r r e n t . T h r e a d P o o l E x e c u t o r . e x e c u t e ( T h r e a d P o o l E x e c u t o r . j a v a : 1394 ) 10 − 2207 : 03 : 07.634101515113 E J a v a B i n d e r : a t c . a . a . a . v . a ( U n k n o w n S o u r c e : 2 ) 10 − 2207 : 03 : 07.634101515113 E J a v a B i n d e r : a t c . a . a . a . t . p ( U n k n o w n S o u r c e : 104 ) 10 − 2207 : 03 : 07.634101515113 E J a v a B i n d e r : a t c . a . a . a . t . j ( U n k n o w n S o u r c e : 102 ) 10 − 2207 : 03 : 07.634101515113 E J a v a B i n d e r : a t c . b . a . b AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2086) 10-22 07:03:07.634 1015 15113 E JavaBinder: at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:848) 10-22 07:03:07.634 1015 15113 E JavaBinder: at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1394) 10-22 07:03:07.634 1015 15113 E JavaBinder: at c.a.a.a.v.a(Unknown Source:2) 10-22 07:03:07.634 1015 15113 E JavaBinder: at c.a.a.a.t.p(Unknown Source:104) 10-22 07:03:07.634 1015 15113 E JavaBinder: at c.a.a.a.t.j(Unknown Source:102) 10-22 07:03:07.634 1015 15113 E JavaBinder: at c.b.a.bAbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2086)10−2207:03:07.634101515113EJavaBinder:atjava.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:848)10−2207:03:07.634101515113EJavaBinder:atjava.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1394)10−2207:03:07.634101515113EJavaBinder:atc.a.a.a.v.a(UnknownSource:2)10−2207:03:07.634101515113EJavaBinder:atc.a.a.a.t.p(UnknownSource:104)10−2207:03:07.634101515113EJavaBinder:atc.a.a.a.t.j(UnknownSource:102)10−2207:03:07.634101515113EJavaBinder:atc.b.a.ba.onTransact(Unknown Source:207)
10-22 07:03:07.634 1015 15113 E JavaBinder: at android.os.Binder.execTransactInternal(Binder.java:1179)
10-22 07:03:07.634 1015 15113 E JavaBinder: at android.os.Binder.execTransact(Binder.java:1143)

1015进程频繁过量使用binder线程导致系统Binder线程池满载, 带来后果就是系统做binder进程通讯变慢亦或停止,界面点击响应不及时

如下图: 1015进程频繁抛出RejectedExcutionException, 该进程频繁进行binder进程间通信,使得系统binder线程池满载(Runing 8个+ active 8个共计16个),导致其他程序在和system_server进程间通信过程中存在等待延迟,拖慢点击事件响应而出现ANR。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/14286.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

知识库搭建:高企创新创业的智慧引擎与未来趋势

在当今这个科技迅猛发展的时代&#xff0c;高新技术企业&#xff08;简称“高企”&#xff09;作为推动经济社会进步的重要力量&#xff0c;正面临着前所未有的创新挑战与机遇。知识库&#xff0c;这一信息时代的关键工具&#xff0c;不仅汇聚了高企内部的丰富知识与经验&#…

D67【python 接口自动化学习】- python基础之数据库

day67 Python操作MySQL基础使用 学习日期&#xff1a;20241113 学习目标&#xff1a;MySQL数据库-- 136 Python操作MySQL基础使用 学习笔记&#xff1a; pymysql 创建MySQL的数据库链接 执行sql语句 总结 Python中使用第三方库&#xff1a;pymysql来操作MySQL&#xff0c;…

容器管理平台KubeSphere的使用

在之前的课程中我们是在minikube中安装了K8S环境,然后通过kubectl命令来管理K8S的,这种用命令来管理的方式虽然对程序员来说看起来很炫酷,但有时候用起来还是挺麻烦的。这节课程给大家介绍一款企业级容器管理平台KubeSphere,使用它能更方便地管理K8S中的容器,希望对大家有…

低代码可视化-uniapp气泡弹窗组件可视化-代码生成器

气泡弹窗组件是产品设计中常用的控件之一&#xff0c;以下是对uniapp气泡弹窗组件可视化的详细解析&#xff1a; 一、组件定义 气泡弹窗组件&#xff08;diy-popover &#xff09;指的是当触发某项操作时&#xff0c;在页面上方或特定位置展示的弹出层容器&#xff0c;容器内…

Unity3D学习FPS游戏(11)敌人AI巡逻(NavMesh)

前言&#xff1a;前面两篇博客已经实现了简单的敌人&#xff0c;但是呢&#xff0c;这样很无趣。因为敌人只会站在原地被攻击&#xff0c;所以本篇我们将实现敌人AI巡逻&#xff0c;让敌人动起来。 敌人AI巡逻 场景丰富一下导航网格NavMesh构建导航网格导航网格优化玩家被当作…

遇到“msvcr120.dll丢失”要怎么解决?详解msvcr120.dll的解决方法

遇到“msvcr120.dll丢失”错误通常表明你的系统缺少一个关键的DLL文件&#xff0c;这是Microsoft Visual C 2013的一部分。这个问题可能导致某些程序无法运行&#xff0c;影响电脑性能。不过&#xff0c;解决这一问题并不复杂。接下来&#xff0c;本文将向你展示几种简单的修复…

git相关知识

前言&#xff1a;在学习git之前首先需要了解几个概念&#xff1a;工作区&#xff0c;暂存区&#xff0c;版本库。 工作区&#xff1a;是电脑上写代码或者文件的目录。 暂存区&#xff1a;一般存放在.git目录下的index中&#xff0c;也称索引。&#xff08;git add&#xff09…

Spring Boot项目的配置文件有哪些?加载优先级谁最高?配置优先级谁最高?

目录 一. 结论 二. .prperties、.yml、.yaml 文件类型简介及注意点 2.1 文件简介 2.2. .prperties&#xff08;默认格式/传统格式&#xff09; 2.3 application.yml&#xff08;主流格式&#xff09; 2.4 application.yaml&#xff08;主流格式&#xff09; 2.5 配置文件…

蓝牙眼镜WT6900HA语音控制芯片方案:开启智能穿戴新篇章

前言&#xff1a; 随着科技的飞速发展&#xff0c;智能穿戴设备已经逐渐融入我们的日常生活。从智能手表到智能手环&#xff0c;再到如今的智能蓝牙眼镜&#xff0c;这些设备不仅改变了我们的生活方式&#xff0c;更引领了一场科技革命。 今天&#xff0c;我们要为大家介绍一款…

项目管理【02】项目开发完整指南

移动端项目开发完整指南&#xff1a;从需求到上线 在移动应用开发过程中&#xff0c;一个项目从最初的需求到最终上线&#xff0c;需要经过多个关键阶段。本文将详细介绍整个开发流程中的最佳实践&#xff0c;帮助开发团队更高效地完成项目。 一、准备阶段 项目启动前的准备工…

快手直播间采集教程,快手引流,快手截流,截流工具,直播间截流,快手直播间采集,获客系统,获客软件

功能&#xff1a; 1.输入快手直播间链接可一键监控直播间 2.可采集新进直播间的人 3.可采集直播间所有动作&#xff0c;包含&#xff1a;发弹幕的人和内容、送礼物的人和送的礼物、点亮爱心的人 4.可一键导出新进直播间的快手ID 5.可一键导出直播间动作列表&#xff0c;也可以筛…

sol机器人pump机器人如何实现盈利的?什么是Pump 扫链机器人?

什么是Pump 扫链机器人&#xff0c;它的盈利逻辑优化策略是什么&#xff1f; Pump 扫链机器人&#xff0c;通过智能化、自动化的买卖操作帮助投资者实现快速盈利。在此基础上&#xff0c;我们对该机器人的盈利逻辑进行了深度优化&#xff0c;涵盖了买入策略和止盈策略的各个方面…

【vue2】13.自定义指令

目录 自定义指令 自定义指令的作用? 自定义指令的使用步骤? 1. 注册 (全局注册 或 局部注册) 2. 标签上 v-指令名 使用 自定义指令 - 指令的值 1. 通过指令的值相关语法&#xff0c;可以应对更复杂指令封装场景 2. 指令值的语法&#xff1a; 自定义指令 - v-loading…

【LLM】Agent的相关Benchmark

note 文章目录 note一、SuperCLUE-Agent二、AgentBench三、跨系统benchmark&#xff1a;CRAB四、SWE-bench 一、SuperCLUE-Agent SuperCLUE-Agent是一个 Agent智能体中文原生任务能力测评基准&#xff0c;评估方面包括&#xff1a; 工具使用能力&#xff08;调用API、检索API、…

MATLAB用CNN-LSTM神经网络的语音情感分类深度学习研究

全文链接&#xff1a;https://tecdat.cn/?p38258 原文出处&#xff1a;拓端数据部落公众号 在语音处理领域&#xff0c;对语音情感的分类是一个重要的研究方向。本文将介绍如何通过结合二维卷积神经网络&#xff08;2 - D CNN&#xff09;和长短期记忆网络&#xff08;LSTM&…

机器学习基础03

目录 1.KNN算法-分类 1.1样本距离判断 1.1.1欧式距离 1.1.2曼哈顿距离 1.2KNN 算法原理 1.3KNN缺点 1.4API 2.模型选择与调优 2.1保留交叉验证 2.2K-折交叉验证 2.3分层k-折交叉验证Stratified k-fold 2.4其它验证 2.5API 3.模型保存与加载 3.1保存模型 3.2加…

【go从零单排】go语言中testing的几种类型

&#x1f308;Don’t worry , just coding! 内耗与overthinking只会削弱你的精力&#xff0c;虚度你的光阴&#xff0c;每天迈出一小步&#xff0c;回头时发现已经走了很远。 &#x1f4d7;概念 Go 语言中的 testing 包是用于编写和运行测试的标准库。它提供了丰富的功能&…

[笔记]自动化中破解验证码

01需求分析 1.打开一个chrome浏览器 2.输入论坛的网址: http://114.116.2.138:8090/forum.php 3.输入用户名admin 4.输入密码123456 5.点击登录 6.输入验证码 7.再点击登录 02准备工作 selenium环境搭建 参考地址: https://blog.csdn.net/python_jeff/article/details…

2024下半年软考系统架构设计师案例分析题试题与答案

解析中包含所有真题图片 解析中包含所有真题图片 解析中包含所有真题图片 解析中包含所有真题图片 第一题 解析见&#xff08;点我&#xff09;&#xff1a;https://blog.csdn.net/u014624241/article/details/143701384 第二题 解析见&#xff08;点我&#xff09;&#…

使用 Python 和 Selenium 解决 hCaptcha:完整指南

如果你跟我一样&#xff0c;你可能也曾遇到过在抓取数据或自动化任务时试图绕过 hCaptcha 的挫折感。你懂的&#xff0c;hCaptcha 弹出来&#xff0c;你的脚本就戛然而止。但别担心&#xff01;我们都经历过。好消息是&#xff0c;用 Python 和 Selenium 解决 hCaptcha 挑战并不…