其实和app无关的anr问题分析

每个Android程序员都会遇到anr问题,anr问题的根源是代码处理中超时,例如超时广播处理超时10s之类的。处理的方法百度google可以见到千篇一律的主线程不要做耗时操作,这个是没错,不过依据我个人这几年的经验来看,大部分app遇到的anr问题和app自生是没有任何关系的。看一份日志:

08-19 12:14:57.269475  1111  1130 E ANRManager: ANR in com.android.incallui, time=104273863
08-19 12:14:57.269475  1111  1130 E ANRManager: Reason: Broadcast of Intent { act=android.intent.action.SCREEN_OFF flg=0x50000010 }
08-19 12:14:57.269475  1111  1130 E ANRManager: Load: 9.35 / 8.88 / 8.57
08-19 12:14:57.269475  1111  1130 E ANRManager: Android time :[2017-08-19 12:14:57.26] [104277.344]
08-19 12:14:57.269475  1111  1130 E ANRManager: CPU usage from 8312ms to 0ms ago:
08-19 12:14:57.269475  1111  1130 E ANRManager:   99% 1013/kworker/5:2: 0% user + 99% kernel
08-19 12:14:57.269475  1111  1130 E ANRManager:   12% 1111/system_server: 8.9% user + 3.3% kernel / faults: 10372 minor 39 major
08-19 12:14:57.269475  1111  1130 E ANRManager:   5% 19573/com.android.systemui: 2.6% user + 2.4% kernel / faults: 1851 minor 19 major
08-19 12:14:57.269475  1111  1130 E ANRManager:   4.9% 334/surfaceflinger: 2.1% user + 2.7% kernel / faults: 309 minor
08-19 12:14:57.269475  1111  1130 E ANRManager:   2.6% 6479/com.netease.mail: 1.9% user + 0.7% kernel / faults: 3681 minor 119 major
08-19 12:14:57.269475  1111  1130 E ANRManager:   2.4% 215/mmcqd/0: 0% user + 2.4% kernel
08-19 12:14:57.269475  1111  1130 E ANRManager:   0.7% 362/fingerprintd: 0% user + 0.7% kernel / faults: 99 minor 1 major
08-19 12:14:57.269475  1111  1130 E ANRManager:   2% 6614/com.netease.mail:pushservice: 1.2% user + 0.8% kernel / faults: 4560 minor 60 major
08-19 12:14:57.269475  1111  1130 E ANRManager:   0% 32044/kworker/8:1: 0% user + 0% kernel
08-19 12:14:57.269475  1111  1130 E ANRManager:   1.2% 7718/cn.kidyn.qdmedical160:pushservice: 0.8% user + 0.3% kernel / faults: 3180 minor 28 major
08-19 12:14:57.269475  1111  1130 E ANRManager:   0.6% 61/dlpt_notify_thr: 0% user + 0.6% kernel
trace如下:

----- pid 2378 at 2017-08-19 12:14:53 -----
Cmd line: com.android.incallui
...

"main" prio=5 tid=1 Native
  | group="main" sCount=1 dsCount=0 obj=0x76af3f88 self=0x7f8703c400
  | sysTid=2378 nice=0 cgrp=default sched=0/0 handle=0x7f8aec02c0
  | state=S schedstat=( 186406401691 149117611257 631811 ) utm=14323 stm=4317 core=7 HZ=100
  | stack=0x7fc2bda000-0x7fc2bdc000 stackSize=8MB
  | held mutexes=
  at android.hardware.SystemSensorManager$BaseEventQueue.nativeDisableSensor(Native method)
  at android.hardware.SystemSensorManager$BaseEventQueue.disableSensor(SystemSensorManager.java:417)
  at android.hardware.SystemSensorManager$BaseEventQueue.removeAllSensors(SystemSensorManager.java:347)
  at android.hardware.SystemSensorManager.unregisterListenerImpl(SystemSensorManager.java:155)
  - locked <0x019000a9> (a java.util.HashMap)
  at android.hardware.SensorManager.unregisterListener(SensorManager.java:625)
  at android.view.OrientationEventListener.disable(OrientationEventListener.java:108)
  at com.android.incallui.InCallActivity.onStop(InCallActivity.java:470)
  at android.app.Instrumentation.callActivityOnStop(Instrumentation.java:1289)
  at android.app.Activity.performStop(Activity.java:6413)
  at android.app.ActivityThread.handleSleeping(ActivityThread.java:3845)
  at android.app.ActivityThread.-wrap19(ActivityThread.java:-1)
  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1672)
  at android.os.Handler.dispatchMessage(Handler.java:111)
  at android.os.Looper.loop(Looper.java:207)
  at android.app.ActivityThread.main(ActivityThread.java:5727)
  at java.lang.reflect.Method.invoke!(Native method)
  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:891)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:752)


mainlog中是说处理广播超时,如果是广播处理超时那么trace日志中主线程堆栈一定是在广播处理的onReceive中,但是可见trace中的堆栈和anr所报没有啥关系。

其实在mainlog中已经给出了anr原因的解释,pid为1013的进程占用了99%的cpu,而且全部是在运行kernel层的代码。

ANRManager处理超时是不会管具体超时原因的,任何超时都会导致正在处理的app进程抛anr出来,但是有可能和app没有任何关系,anr的出口肯定是app,抛出anr的app只是正好撞在了枪口上。由于这个anr机制的原因,anr问题永远不会被消灭,无论你的app代码写的效率再高再完美。



<think>好的,我现在需要帮助用户了解ANR的原因解决方案。首先,我得回忆一下之前学过的关于ANR的知识,并结合提供的引用内容来组织回答。用户的问题比较明确,但可能需要详细的结构化信息。 首先,ANR是什么?根据引用[1][3],ANR即应用程序无响应,通常是因为主线程被阻塞超过一定时间。接下来要分析原因。根据引用内容,主要原因包括主线程执行耗时操作、过多UI操作、内存问题、线程管理不当等。 需要分点列出原因,每个原因下可能需要例子或更详细的说明。例如,主线程的耗时操作可以举数据库查询或网络请求的例子。然后,解决方案部分应该对应每个原因给出解决方法,比如使用子线程或协程处理耗时任务,优化UI渲染等。 另外,用户提供的引用中提到了导出ANR日志进行分析,这也是解决方案的一部分,应该包含进去。可能还需要提到工具的使用,比如Android Studio的Profiler来检测性能问题。 需要确保回答结构清晰,分点说明,可能用标题来分隔原因解决方案。同时,注意引用标识的正确添加,如每个引用来源的末尾加上[^1]、[^2]或[^3]。 还要检查是否符合系统级指令的要求,比如使用正确的中文,数学公式的格式(虽然这里可能用不上,但如果有的话要留意),以及生成相关问题。生成的问题需要与ANR相关,可能涉及检测工具、避免主线程阻塞的方法、ANR日志分析步骤等。 最后,确保语言口语化,避免使用专业术语过多,或者适当解释术语,让用户容易理解。比如解释主线程是什么,为什么阻塞会导致ANR等。 现在开始组织内容: 首先定义ANR,说明其发生的条件(如主线程阻塞5秒)。然后分点列出原因,每个原因对应解决方案。可能需要分成几个小节,如“原因分析“解决方案”,每个部分用编号或项目符号列出。确保每个引用都正确标注,比如在提到导出日志时引用[2],在原因部分引用[1][3]。 生成的问题可能需要包括如何检测ANR、常见场景、工具使用等。需要三个问题,如用户示例中的那样。 检查是否有遗漏的信息,比如引用[3]提到的广播接收器超时10秒的情况,这也是ANR的一种情况,需要包含在原因中。还有内存使用不当导致系统清理应用的情况,这可能涉及到内存泄漏或高内存占用,解决方案需要包括内存优化。 总结下来,回答的结构大致如下: 1. ANR的定义触发条件 2. 原因分析(分点列出,每个原因对应引用) 3. 解决方案(分点对应原因,加上日志分析等) 4. 相关问题生成 需要确保每个引用只在被提及的地方标注,比如导出日志对应引用[2],内存问题对应引用[3]等。同时,代码示例如果有的话可能需要用代码块,但用户的问题可能不需要代码,但解决方案中提到使用子线程时可以给出简单的示例,比如使用AsyncTask或Kotlin协程。 不过用户提供的引用中没有代码示例,所以可能不需要添加。但根据用户提供的示例,快速排序有代码块,但当前问题可能不需要。所以可能保持回答为纯文本。 最后,生成的问题要相关,比如关于检测工具、避免ANR的最佳实践、分析日志的方法等。</think>### ANRApplication Not Responding)原因及解决方案 #### 一、ANR的定义与触发条件 当应用的主线程被阻塞超过**5秒**(处理广播接收器时超过**10秒**),系统会触发ANR,导致用户感知卡顿或弹窗提示[^3]。 --- #### 二、原因分析 1. **主线程执行耗时操作** - **表现**:如数据库查询、复杂计算、同步网络请求等。 - **示例**:在`Activity`的`onCreate()`中加载大量数据。 2. **UI渲染过载** - **表现**:频繁绘制复杂视图或动画,导致主线程无法及时响应输入事件。 3. **内存使用不当** - **表现**:内存泄漏或过度占用内存,触发系统强制回收资源,间接阻塞主线程。 4. **线程管理问题** - **表现**:线程池配置不合理(如线程数不足),或子线程未释放资源引发死锁。 5. **跨进程通信(IPC)阻塞** - **表现**:与`Service`或`ContentProvider`交互时,对方进程未及时响应。 --- #### 三、解决方案 1. **异步处理耗时任务** - **方法**:使用`AsyncTask`、`HandlerThread`、Kotlin协程等将任务移至子线程。 - **示例**:网络请求通过`Retrofit`的`enqueue()`异步回调处理。 2. **优化UI渲染** - **方法**:减少布局嵌套、使用`RecyclerView`替代`ListView`、避免`onDraw()`中复杂计算。 3. **内存分析与优化** - **工具**:通过Android Profiler检测内存泄漏,使用`LeakCanary`自动监控。 4. **合理配置线程池** - **方法**:根据任务类型(CPU密集型/IO密集型)动态调整线程池大小,避免资源竞争[^3]。 5. **导出并分析ANR日志** - **步骤**:通过`adb pull /data/anr/traces.txt`获取日志,定位阻塞的堆栈信息。 6. **广播接收器超时控制** - **方法**:在`BroadcastReceiver`中启动`IntentService`处理任务,而非直接执行操作。 --- #### 四、典型场景与修复示例 **场景**:应用启动时加载本地大文件导致ANR。 **修复**: ```kotlin // 主线程中仅触发异步任务 CoroutineScope(Dispatchers.Main).launch { withContext(Dispatchers.IO) { loadLargeFile() } // 子线程执行 } ``` ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值