记一次分析解决ANR过程

2024-04-10 08:48
文章标签 分析 解决 过程 一次 anr

本文主要是介绍记一次分析解决ANR过程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

ANR即Application Not Responding,一直觉得只要在主线程中注意不要执行耗时操作就不会发生ANR,然而事实告诉我我还是too young too simple,sometimes naive 啊。以前也没遇到过ANR,没分析过ANR,问过同事,同事也说没弄过,没办法只能自己找资料了。

ANR问题的分类

InputDispatchingTimedOut
应用程序主线程在5秒内没有完成用户的input事件(比如按键事件、屏幕触摸事件)

Service Timeout
应用程序没有执行完成service的bind/create/start/destroy/unbind操作 前台服务20秒超时,后台服务200秒超时

Broadcast Timeout
应用程序在规定时间内没有执行完成onReceive操作 前台广播10秒超时,后台广播60秒超时(BROADCAST_FG_TIMEOUT /BROADCAST_FG_TIMEOUT)

Content Provider Timeout
应用程序在20秒内没有执行完成ContentProvider相关操作

经过我查看log信息发现
Reason: Input dispatching timed out (Waiting because the touched window has not finished processing the input events that were previously delivered to it.)
Load: 0.9 / 0.57 / 0.68
CPU usage from 2505ms to -3307ms ago:
94% 20357/com.richeninfo.cmoa: 94% user+ 0.3% kernel / faults: 1 minor
22% 810/system_server: 17% user + 5.1% kernel / faults: 1061 minor
0.5% 146/debuggerd: 0.2% user + 0.3% kernel / faults: 2717 minor
3.4% 977/com.android.systemui: 3.2% user + 0.1% kernel / faults: 11 minor
1.8% 1310/com.android.phone: 1.5% user + 0.3% kernel
1.3% 9586/adbd: 0% user + 1.3% kernel / faults: 629 minor
1% 1345/com.miui.whetstone: 1% user + 0% kernel
0.1% 1329/com.xiaomi.finddevice: 0% user + 0% kernel
0.8% 11382/kworker/0:0: 0% user + 0.8% kernel
0.8% 22403/com.mi.liveassistant: 0.1% user + 0.6% kernel
0.5% 925/com.xiaomi.xmsf: 0.3% user + 0.1% kernel
0.1% 3/ksoftirqd/0: 0% user + 0.1% kernel
0% 1322/com.xiaomi.mitunes: 0% user + 0% kernel
0% 15074/com.android.defcontainer: 0% user + 0% kernel / faults: 14 minor
0% 20675/android.process.media: 0% user + 0% kernel / faults: 14 minor
0% 15/migration/2: 0% user + 0% kernel
0.1% 37/cfinteractive: 0% user + 0.1% kernel
0% 107/dhd_watchdog_th: 0% user + 0% kernel
0% 1293/com.xiaomi.metoknlp: 0% user + 0% kernel / faults: 2 minor
0% 5809/kworker/u10:2: 0% user + 0% kernel
0% 13679/kworker/3:3: 0% user + 0% kernel
0% 13901/com.sohu.inputmethod.sogou: 0% user + 0% kernel
0.1% 20282/com.xiaomi.gamecenter: 0.1% user + 0% kernel
0.1% 26880/com.tencent.mobileqq:MSF: 0.1% user + 0% kernel / faults: 6 minor
1.2% TOTAL: 0% user + 0% kernel + 1.2% iowait + 0% softirq
CPU usage from 2756ms to 3285ms later with 99% awake:
100% 20357/com.richeninfo.cmoa: 100% user + 0% kernel
100% 20357/richeninfo.cmoa: 100% user + 0% kernel
5.6% 810/system_server: 1.8% user + 3.7% kernel
3.7% 826/ActivityManager: 1.8% user + 1.8% kernel
1.8% 969/CMEM Purge: 1.8% user + 0% kernel
0.7% 15/migration/2: 0% user + 0.7% kernel
1.1% 11382/kworker/0:0: 0% user + 1.1% kernel
2.2% TOTAL: 0% user + 0% kernel + 2.2% iowait

经过我查资料得知:

从LOG可以看出ANR的类型,CPU的使用情况,如果CPU使用量接近100%,说明当前设备很忙,有可能是CPU饥饿导致了ANR
如果CPU使用量很少,说明主线程被BLOCK了
如果IOwait很高,说明ANR有可能是主线程在进行I/O操作造成的

所以看我的这里打印出来log的信息几个关键点是
1.Reason: Input dispatching timed out
2. CPU usage from 2505ms to -3307ms ago:
94% 20357/com.richeninfo.cmoa: 94% user+ 0.3% kernel / faults: 1 minor
3.2.2% iowait

所以我这里导致ANR的原因应该是CPU不足。

仅仅查看log的信息还不足以帮我们定位到ANR的原因,所以需要去看data/anr/trace文件或者data/system/dropbox/下的log日志(真机需要root,模拟器用DDMS如果看不了的话按照这篇文章http://www.cnblogs.com/Stay-Hungry-Stay-Foolish/p/6940219.html去做就可以。)
我的trace文件信息如下:
—– pid 21029 at 2017-08-30 12:41:54 —–
Cmd line: com.richeninfo.cmoa

JNI: CheckJNI is off; workarounds are off; pins=0; globals=329

DALVIK THREADS:
(mutexes: tll=0 tsl=0 tscl=0 ghl=0)

“main” prio=5 tid=1 SUSPENDED
| group=”main” sCount=1 dsCount=0 obj=0x41d6bcd8 self=0x41d5a408
| sysTid=21029 nice=0 sched=0/0 cgrp=apps handle=1074229588
| state=S schedstat=( 7063110348 1097534177 6665 ) utm=669 stm=37 core=0
at android.support.v4.view.ViewPager.populate(ViewPager.java:~1162)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:666)
at android.support.v4.view.ViewPager.setCurrentItemInternal(ViewPager.java:628)
at android.support.v4.view.ViewPager.setCurrentItem(ViewPager.java:620)
at com.richeninfo.cmoa.widget.AutoScrollViewPager.onTouchEvent(AutoScrollViewPager.java:219)
at android.view.View.dispatchTouchEvent(View.java:7719)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2210)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1945)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at com.android.internal.policy.impl.PhoneWindowDecorView.superDispatchTouchEvent(PhoneWindow.java:2144)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1589)
at android.app.Activity.dispatchTouchEvent(Activity.java:2582)
at com.android.internal.policy.impl.PhoneWindowDecorView.dispatchTouchEvent(PhoneWindow.java:2092)
at android.view.View.dispatchPointerEvent(View.java:7899)
at android.view.ViewRootImpl ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4009)
at android.view.ViewRootImpl.ViewPostImeInputStage.onProcess(ViewRootImpl.java:3886)
at android.view.ViewRootImpl.InputStage.deliver(ViewRootImpl.java:3447)
at android.view.ViewRootImpl.InputStage.onDeliverToNext(ViewRootImpl.java:3497)
at android.view.ViewRootImpl.InputStage.forward(ViewRootImpl.java:3466)
at android.view.ViewRootImpl.AsyncInputStage.forward(ViewRootImpl.java:3573)
at android.view.ViewRootImpl.InputStage.apply(ViewRootImpl.java:3474)
at android.view.ViewRootImpl.AsyncInputStage.apply(ViewRootImpl.java:3630)
at android.view.ViewRootImpl.InputStage.deliver(ViewRootImpl.java:3447)
at android.view.ViewRootImpl.InputStage.onDeliverToNext(ViewRootImpl.java:3497)
at android.view.ViewRootImpl.InputStage.forward(ViewRootImpl.java:3466)
at android.view.ViewRootImpl.InputStage.apply(ViewRootImpl.java:3474)
at android.view.ViewRootImpl.InputStage.deliver(ViewRootImpl.java:3447)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5594)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5574)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5545)
at android.view.ViewRootImpl.WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5677)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:176)
at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:5650)
at android.view.ViewRootImpl.ConsumeBatchedInputRunnable.run(ViewRootImpl.java:5696)
at android.view.Choreographer.CallbackRecord.run(Choreographer.java:761)
at android.view.Choreographer.doCallbacks(Choreographer.java:574)
at android.view.Choreographer.doFrame(Choreographer.java:542)
at android.view.Choreographer.FrameDisplayEventReceiver.run(Choreographer.java:747)
at android.os.Handler.handleCallback(Handler.java:733)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5135)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit.MethodAndArgsCaller.run(ZygoteInit.java:798)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:614)
at dalvik.system.NativeStart.main(Native Method)

从这些信息中首先看到线程的状态为”main” prio=5 tid=1 SUSPENDED
而经过一位朋友提示线程状态为SUSPENDED 只有在debug的时候会这样,可是我没在debug啊,所以网上查到下面资料图:
thread.png
可以看到资料说这种状态通常是由于GC或者debug,所以我的情况应该是就GC了,这也验证了前面说的CPU不足的原因。
再看到trace里另外一个关键点:
com.richeninfo.cmoa.widget.AutoScrollViewPager.onTouchEvent(AutoScrollViewPager.java:219)
这里指定在我的项目中其他同事引入的第三方控件添加的onTouchEvent监听里因为某些操作频繁引起GC导致CPU不足,前面log信息打印出的:
Reason: Input dispatching timed out(Waiting because the touched window has not finished processing the input events that were previously delivered to it.)
说明这CPU不足导致无法相应下一个input events导致ANR。
那就去看看onTouchEvent里都执行了什么鬼操作。

 announcePager.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:announcePager.stopAutoScroll();break;case MotionEvent.ACTION_MOVE:announcePager.startAutoScroll();break;case MotionEvent.ACTION_UP:announcePager.startAutoScroll();break;default:break;}return false;}});

可以看到相应了三个action,那么就去看看startAutoScroll()stopAutoScroll()都写了什么。

public void startAutoScroll(int delayTimeInMills) {isAutoScroll = true;sendScrollMessage(delayTimeInMills);}/*** stop auto scroll*/public void stopAutoScroll() {isAutoScroll = false;handler.removeMessages(SCROLL_WHAT);}/*** set the factor by which the duration of sliding animation will change*/public void setScrollDurationFactor(double scrollFactor) {scroller.setScrollDurationFactor(scrollFactor);}private void sendScrollMessage(long delayTimeInMills) {/** remove messages before, keeps one message is running at most **/handler.removeMessages(SCROLL_WHAT);handler.sendEmptyMessageDelayed(SCROLL_WHAT, delayTimeInMills);}

看到是handler在发送消息并且每次发送之前都要把前面的消息移除。
结合我操作APP发生ANR的时机,判断问题应该是出现在action_move响应太频繁,导致频繁startAutoScroll();然后方法内部里频繁handler.removeMessages(),这样被remove的消息由于垃圾回收机制频繁引起GC,所以就导致了CPU不足,这样似乎可以验证前面的说法。

问题找到了,那就要解决,这个解决也简单,直接把action_move里的
startAutoScroll()注释掉就OK了,其实这里也不需要在action_move里执行startAutoScroll(),因为action_up里已经执行了startAutoScroll()。

这样ANR就分析解决完毕了。有了这次经验,以后相信自己能比较好应对ANR。。。认真分析trace信息和log日志.

这篇关于记一次分析解决ANR过程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/890598

相关文章

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

作业提交过程之HDFSMapReduce

作业提交全过程详解 (1)作业提交 第1步:Client调用job.waitForCompletion方法,向整个集群提交MapReduce作业。 第2步:Client向RM申请一个作业id。 第3步:RM给Client返回该job资源的提交路径和作业id。 第4步:Client提交jar包、切片信息和配置文件到指定的资源提交路径。 第5步:Client提交完资源后,向RM申请运行MrAp

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

如何解决线上平台抽佣高 线下门店客流少的痛点!

目前,许多传统零售店铺正遭遇客源下降的难题。尽管广告推广能带来一定的客流,但其费用昂贵。鉴于此,众多零售商纷纷选择加入像美团、饿了么和抖音这样的大型在线平台,但这些平台的高佣金率导致了利润的大幅缩水。在这样的市场环境下,商家之间的合作网络逐渐成为一种有效的解决方案,通过资源和客户基础的共享,实现共同的利益增长。 以最近在上海兴起的一个跨行业合作平台为例,该平台融合了环保消费积分系统,在短

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

MOLE 2.5 分析分子通道和孔隙

软件介绍 生物大分子通道和孔隙在生物学中发挥着重要作用,例如在分子识别和酶底物特异性方面。 我们介绍了一种名为 MOLE 2.5 的高级软件工具,该工具旨在分析分子通道和孔隙。 与其他可用软件工具的基准测试表明,MOLE 2.5 相比更快、更强大、功能更丰富。作为一项新功能,MOLE 2.5 可以估算已识别通道的物理化学性质。 软件下载 https://pan.quark.cn/s/57

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip

衡石分析平台使用手册-单机安装及启动

单机安装及启动​ 本文讲述如何在单机环境下进行 HENGSHI SENSE 安装的操作过程。 在安装前请确认网络环境,如果是隔离环境,无法连接互联网时,请先按照 离线环境安装依赖的指导进行依赖包的安装,然后按照本文的指导继续操作。如果网络环境可以连接互联网,请直接按照本文的指导进行安装。 准备工作​ 请参考安装环境文档准备安装环境。 配置用户与安装目录。 在操作前请检查您是否有 sud

线性因子模型 - 独立分量分析(ICA)篇

序言 线性因子模型是数据分析与机器学习中的一类重要模型,它们通过引入潜变量( latent variables \text{latent variables} latent variables)来更好地表征数据。其中,独立分量分析( ICA \text{ICA} ICA)作为线性因子模型的一种,以其独特的视角和广泛的应用领域而备受关注。 ICA \text{ICA} ICA旨在将观察到的复杂信号