android ANR異常定位分析

一. 問題定位

1. 發(fā)生anr異常 會在data/anr目錄下 存在異常記錄

微信圖片_20230328095414.png
微信圖片_20230328095420.png

使用adb pull data/anr 因?yàn)闆]有權(quán)限 會獲取失敗 更換命令 使用adb bugreport 打包anr信息
成功后 會告知存放位置。解壓后文件目錄:


1679968766837.png

文件夾中兩處 都有相關(guān)錯誤信息
(1)FS/data/anr下 這個更好定位
(2)bugreport-PEXMOO-...文件

定位問題(1)

打開文件大致內(nèi)容
cmd line 確認(rèn)是當(dāng)前應(yīng)用包名 Cmd line: com.test.test

----- pid 27325 at 2023-03-24 14:36:23 -----
Cmd line: com.test.test
Build fingerprint: 'Xiaomi/renoir/renoir:11/RKQ1.201112.002/V12.5.8.0.RKICNXM:user/release-keys'
ABI: 'arm64'
Build type: optimized
Zygote loaded classes=21457 post zygote classes=1841
Dumping registered class loaders
#0 dalvik.system.PathClassLoader: [], parent #1
#1 java.lang.BootClassLoader: [], no parent
#2 dalvik.system.PathClassLoader: [/system/framework/tcmclient.jar], parent #0
#3 dalvik.system.PathClassLoader: [], parent #0

全局搜 "main" prio=5 確認(rèn)問題點(diǎn)

"main" prio=5 tid=1 Blocked
  | group="main" sCount=1 dsCount=0 flags=1 obj=0x72c36338 self=0xb400006fa7094c00
  | sysTid=27325 nice=-10 cgrp=top-app sched=0/0 handle=0x702e4cc4f8
  | state=S schedstat=( 168352756660 13839364110 211677 ) utm=14483 stm=2351 core=5 HZ=100
  | stack=0x7fd4b47000-0x7fd4b49000 stackSize=8192KB
  | held mutexes=
  at android.os.MessageQueue.enqueueMessage(MessageQueue.java:557)
  - waiting to lock <0x03180f01> (a android.os.MessageQueue)
  at android.os.Handler.enqueueMessage(Handler.java:778)
  at android.os.Handler.sendMessageAtTime(Handler.java:727)
  at android.view.ViewRootImpl$ViewRootHandler.sendMessageAtTime(ViewRootImpl.java:5135)
  at android.os.Handler.sendMessageDelayed(Handler.java:697)
  at android.os.Handler.postDelayed(Handler.java:499)
  at android.view.HandlerActionQueue.executeActions(HandlerActionQueue.java:85)
  - locked <0x0196e1a6> (a android.view.HandlerActionQueue)
  at android.view.View.dispatchAttachedToWindow(View.java:20667)
  at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3522)
  at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3529)
  at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3529)
  at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:3529)
  ... repeated 2 times
  at android.view.ViewGroup.addViewInner(ViewGroup.java:5316)
  at android.view.ViewGroup.addView(ViewGroup.java:5102)
  at android.view.ViewGroup.addView(ViewGroup.java:5039)
  at androidx.recyclerview.widget.RecyclerView$5.addView(RecyclerView.java:889)
  at androidx.recyclerview.widget.ChildHelper.addView(ChildHelper.java:107)
  at androidx.recyclerview.widget.RecyclerView$LayoutManager.addViewInt(RecyclerView.java:8902)
  at androidx.recyclerview.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:8860)
  at androidx.recyclerview.widget.RecyclerView$LayoutManager.addView(RecyclerView.java:8848)
  at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1645)
  at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1591)
  at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:668)
  at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4309)
  at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:4012)
  at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4578)
  at android.view.View.layout(View.java:23125)
  at android.view.ViewGroup.layout(ViewGroup.java:6460)
  at androidx.viewpager2.widget.ViewPager2.onLayout(ViewPager2.java:527)
  at android.view.View.layout(View.java:23125)
  at android.view.ViewGroup.layout(ViewGroup.java:6460)
  at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1103)
  at android.view.View.layout(View.java:23125)
  at android.view.ViewGroup.layout(ViewGroup.java:6460)
  at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
  at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
  at android.view.View.layout(View.java:23125)
  at android.view.ViewGroup.layout(ViewGroup.java:6460)
  at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
  at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
  at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
  at android.view.View.layout(View.java:23125)
  at android.view.ViewGroup.layout(ViewGroup.java:6460)
  at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
  at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
  at android.view.View.layout(View.java:23125)
  at android.view.ViewGroup.layout(ViewGroup.java:6460)
  at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
  at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
  at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
  at android.view.View.layout(View.java:23125)
  at android.view.ViewGroup.layout(ViewGroup.java:6460)
  at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
  at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
  at com.android.internal.policy.DecorView.onLayout(DecorView.java:797)
  at android.view.View.layout(View.java:23125)
  at android.view.ViewGroup.layout(ViewGroup.java:6460)
  at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:3626)
  at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3085)
  at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2075)
  at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8522)
  at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1077)
  at android.view.Choreographer.doCallbacks(Choreographer.java:897)
  at android.view.Choreographer.doFrame(Choreographer.java:826)
  at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1062)
  at android.os.Handler.handleCallback(Handler.java:938)
  at android.os.Handler.dispatchMessage(Handler.java:99)
  at android.os.Looper.loop(Looper.java:233)
  at android.app.ActivityThread.main(ActivityThread.java:8052)
  at java.lang.reflect.Method.invoke(Native method)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:656)
  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:967)


"main" prio=5 tid=1 Blocked
mian:主線程
prio =5: 線程優(yōu)先級
Blocked: 當(dāng)前線程狀態(tài) 表示當(dāng)前主線程阻塞 ANR

(線程的狀態(tài):
NEW - 創(chuàng)建狀態(tài)
RUNNABLE - 就緒或運(yùn)行狀態(tài)
BLOCKED - 阻塞狀態(tài)
WATING - 等待狀態(tài)
TIMED_WAITING - 定時等待狀態(tài)
TERMINATED - 終止?fàn)顟B(tài))

繼續(xù)問題定位 當(dāng)前信息沒有自己代碼的問題 都是系統(tǒng)代碼 但是代碼中有兩處lock

  • waiting to lock <0x03180f01> (a android.os.MessageQueue)
  • locked <0x0196e1a6> (a android.view.HandlerActionQueue)
    根據(jù)地址 搜索調(diào)用位置 0x03180f01
"Timer-19" prio=5 tid=123 Runnable
  | group="main" sCount=0 dsCount=0 flags=0 obj=0x14b07060 self=0x6f8a648c00
  | sysTid=6393 nice=0 cgrp=top-app sched=0/0 handle=0x6f25357cc0
  | state=R schedstat=( 70680442813 8390554181 396852 ) utm=6118 stm=949 core=7 HZ=100
  | stack=0x6f25254000-0x6f25256000 stackSize=1043KB
  | held mutexes= "mutator lock"(shared held)
  at android.os.MessageQueue.enqueueMessage(MessageQueue.java:586)
  - locked <0x03180f01> (a android.os.MessageQueue)
  at android.os.Handler.enqueueMessage(Handler.java:778)
  at android.os.Handler.sendMessageAtTime(Handler.java:727)
  at android.view.ViewRootImpl$ViewRootHandler.sendMessageAtTime(ViewRootImpl.java:5135)
  at android.os.Handler.sendMessageDelayed(Handler.java:697)
  at android.os.Handler.post(Handler.java:427)
  at android.view.View.post(View.java:18950)
  at com.xxx.xxxx.webView.BaseWebViewClient$TT.run(BaseWebViewClient.kt:23)
  at java.util.TimerThread.mainLoop(Timer.java:562)
  at java.util.TimerThread.run(Timer.java:512)

然后發(fā)現(xiàn)在自己代碼中的問題點(diǎn)
at com.xxx.xxxx.webView.BaseWebViewClient$TT.run(BaseWebViewClient.kt:23)

定位問題(2)

打開文件大概信息

========================================================
== dumpstate: 2023-03-24 15:17:39
========================================================

Build: RKQ1.201112.002 test-keys
Build fingerprint: 'Xiaomi/renoir/renoir:11/RKQ1.201112.002/V12.5.8.0.RKICNXM:user/release-keys'
Bootloader: unknown
Radio: 4.0-c7-11.1873.2-1026_2256_b83f4dadbc,4.0-c7-11.1873.2-1026_2256_b83f4dadbc
Network: ,
Module Metadata version: 30
Kernel: Linux version 5.4.86-qgki-g481f7eca2ed5 (builder@m1-xm-ota-bd044.bj.idc.xiaomi.com) (Android (6443078 based on r383902) clang version 11.0.1 (https://android.googlesource.com/toolchain/llvm-project b397f81060ce6d701042b782172ed13bee898b79), LLD 11.0.1 (/buildbot/tmp/tmp6_m7QH b397f81060ce6d701042b782172ed13bee898b79)) #1 SMP PREEMPT Wed Oct 27 15:02:49 CST 2021
Command line: ramoops_memreserve=4M log_buf_len=256K rcupdate.rcu_expedited=1 rcu_nocbs=0-7 console=ttyMSM0,115200n8 androidboot.hardware=qcom androidboot.console=ttyMSM0 androidboot.memcg=1 lpm_levels.sleep_disabled=1 video=vfb:640x400,bpp=32,memsize=3072000 msm_rtb.filter=0x237 service_locator.enable=1 androidboot.usbcontroller=a600000.dwc3 swiotlb=0 loop.max_part=7 cgroup.memory=nokmem,nosocket pcie_ports=compat loop.max_part=7 iptable_raw.raw_before_defrag=1 ip6table_raw.raw_before_defrag=1 buildvariant=user  androidboot.verifiedbootstate=green androidboot.keymaster=1 androidboot.vbmeta.device=PARTUUID=65cc4597-

搜索關(guān)鍵字 VM TRACES AT LAST ANR 確認(rèn)當(dāng)前包名 Cmd line: com.test.test

------ 0.007s was the duration of 'VM TRACES JUST NOW' ------
------ VM TRACES AT LAST ANR (/data/anr/anr_2023-03-24-14-36-34-749: 2023-03-24 14:36:42) ------

----- pid 27325 at 2023-03-24 14:36:35 -----
Cmd line: com.test.test
Build fingerprint: 'Xiaomi/renoir/renoir:11/RKQ1.201112.002/V12.5.8.0.RKICNXM:user/release-keys'
ABI: 'arm64'
Build type: optimized
Zygote loaded classes=21457 post zygote classes=1862

后面的步驟和(1)一致

2. 集成了bugly之類第三方異常捕捉上報工具,這里會有詳細(xì)的信息 定位方式如上

1679974685314(1).png

三. 問題發(fā)生原因

ANR(Application Not Responding) 應(yīng)用程序無響應(yīng)。如果你應(yīng)用程序在UI線程被阻塞太長時間,就會出現(xiàn)ANR,通常出現(xiàn)ANR,系統(tǒng)會彈出一個提示提示框,讓用戶知道,該程序正在被阻塞,是否繼續(xù)等待還是關(guān)閉。
ANR類型
出現(xiàn)ANR的一般有以下幾種類型:
1:KeyDispatchTimeout(常見)
input事件在5S內(nèi)沒有處理完成發(fā)生了ANR。
logcat日志關(guān)鍵字:Input event dispatching timed out
2:BroadcastTimeout
前臺Broadcast:onReceiver在10S內(nèi)沒有處理完成發(fā)生ANR。
后臺Broadcast:onReceiver在60s內(nèi)沒有處理完成發(fā)生ANR。
logcat日志關(guān)鍵字:Timeout of broadcast BroadcastRecord
3:ServiceTimeout
前臺Service:onCreate,onStart,onBind等生命周期在20s內(nèi)沒有處理完成發(fā)生ANR。
后臺Service:onCreate,onStart,onBind等生命周期在200s內(nèi)沒有處理完成發(fā)生ANR
logcat日志關(guān)鍵字:Timeout executing service
4:ContentProviderTimeout
ContentProvider 在10S內(nèi)沒有處理完成發(fā)生ANR。
logcat日志關(guān)鍵字:timeout publishing content providers

ANR出現(xiàn)常見原因
1:主線程頻繁進(jìn)行耗時的IO操作:如數(shù)據(jù)庫讀寫
2:多線程操作的死鎖,主線程被block;
3:主線程被Binder 對端block;
4:System Server中WatchDog出現(xiàn)ANR;
5:service binder的連接達(dá)到上線無法和和System Server通信
6:系統(tǒng)資源已耗盡(管道、CPU、IO)

https://juejin.cn/post/6844903942841712648
https://juejin.cn/post/6844903715313303565#heading-4

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容