亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

全面解析Android之ANR日志

瀏覽:77日期:2022-09-18 08:01:40
目錄一、概述二、ANR產(chǎn)生機(jī)制2.1 輸入事件超時(shí)(5s)2.2 廣播類型超時(shí)(前臺(tái)15s,后臺(tái)60s)2.3 服務(wù)超時(shí)(前臺(tái)20s,后臺(tái)200s)2.4 ContentProvider 類型三、導(dǎo)致ANR的原因3.1 應(yīng)用層導(dǎo)致ANR(耗時(shí)操作)3.2 系統(tǒng)導(dǎo)致ANR四、分析日志4.1 CPU 負(fù)載4.2 內(nèi)存信息4.3 堆棧消息五、典型案例分析5.1 主線程無(wú)卡頓,處于正常狀態(tài)堆棧5.2 主線程執(zhí)行耗時(shí)操作5.3 主線程被鎖阻塞5.4 CPU被搶占5.5內(nèi)存緊張導(dǎo)致ANR5.6 系統(tǒng)服務(wù)超時(shí)導(dǎo)致ANR一、概述

解決ANR一直是Android 開(kāi)發(fā)者需要掌握的重要技巧,一般從三個(gè)方面著手。

開(kāi)發(fā)階段:通過(guò)工具檢查各個(gè)方法的耗時(shí),卡頓情況,發(fā)現(xiàn)一處修改一處。 線上階段:這個(gè)階段主要依靠監(jiān)控工具發(fā)現(xiàn)ANR并上報(bào),比如matrix。 分析階段:如果線上用戶發(fā)生ANR,并且你獲取了一份日志,這就涉及了本文要分享的內(nèi)容——ANR日志分析技巧。二、ANR產(chǎn)生機(jī)制

網(wǎng)上通俗的一段面試答題

ANR——應(yīng)用無(wú)響應(yīng),Activity是5秒,BroadCastReceiver是10秒,Service是20秒。

這句話說(shuō)的很籠統(tǒng),要想深入分析定位ANR,需要知道更多知識(shí)點(diǎn),一般來(lái)說(shuō),ANR按產(chǎn)生機(jī)制,分為4類:

2.1 輸入事件超時(shí)(5s)

InputEvent Timeout

a.InputDispatcher發(fā)送key事件給 對(duì)應(yīng)的進(jìn)程的 Focused Window ,對(duì)應(yīng)的window不存在、處于暫停態(tài)、或通道(input channel)占滿、通道未注冊(cè)、通道異常、或5s內(nèi)沒(méi)有處理完一個(gè)事件,就會(huì)發(fā)生ANR

b.InputDispatcher發(fā)送MotionEvent事件有個(gè)例外之處:當(dāng)對(duì)應(yīng)Touched Window的 input waitQueue中有超過(guò)0.5s的事件,inputDispatcher會(huì)暫停該事件,并等待5s,如果仍舊沒(méi)有收到window的‘finish’事件,則觸發(fā)ANR

c.下一個(gè)事件到達(dá),發(fā)現(xiàn)有一個(gè)超時(shí)事件才會(huì)觸發(fā)ANR

2.2 廣播類型超時(shí)(前臺(tái)15s,后臺(tái)60s)

BroadcastReceiver Timeout

a.靜態(tài)注冊(cè)的廣播和有序廣播會(huì)ANR,動(dòng)態(tài)注冊(cè)的非有序廣播并不會(huì)ANR

b.廣播發(fā)送時(shí),會(huì)判斷該進(jìn)程是否存在,不存在則創(chuàng)建,創(chuàng)建進(jìn)程的耗時(shí)也算在超時(shí)時(shí)間里

c.只有當(dāng)進(jìn)程存在前臺(tái)顯示的Activity才會(huì)彈出ANR對(duì)話框,否則會(huì)直接殺掉當(dāng)前進(jìn)程

d.當(dāng)onReceive執(zhí)行超過(guò)閾值(前臺(tái)15s,后臺(tái)60s),將產(chǎn)生ANR

e.如何發(fā)送前臺(tái)廣播:Intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND)

2.3 服務(wù)超時(shí)(前臺(tái)20s,后臺(tái)200s)

Service Timeout

a.Service的以下方法都會(huì)觸發(fā)ANR:onCreate(),onStartCommand(), onStart(), onBind(), onRebind(), onTaskRemoved(), onUnbind(),

onDestroy().

b.前臺(tái)Service超時(shí)時(shí)間為20s,后臺(tái)Service超時(shí)時(shí)間為200s

c.如何區(qū)分前臺(tái)、后臺(tái)執(zhí)行————當(dāng)前APP處于用戶態(tài),此時(shí)執(zhí)行的Service則為前臺(tái)執(zhí)行。

d.用戶態(tài):有前臺(tái)activity、有前臺(tái)廣播在執(zhí)行、有foreground service執(zhí)行

2.4 ContentProvider 類型

a.ContentProvider創(chuàng)建發(fā)布超時(shí)并不會(huì)ANR

b.使用ContentProviderclient來(lái)訪問(wèn)ContentProverder可以自主選擇觸發(fā)ANR,超時(shí)時(shí)間自己定

client.setDetectNotResponding(PROVIDER_ANR_TIMEOUT);

ps:Activity生命周期超時(shí)會(huì)不會(huì)ANR?——經(jīng)測(cè)試并不會(huì)。

override fun onCreate(savedInstanceState: Bundle?) { Thread.sleep(60000) super.onCreate(savedInstanceState) setContentView(R.layout.activity_main)}三、導(dǎo)致ANR的原因

很多開(kāi)發(fā)者認(rèn)為,那就是耗時(shí)操作導(dǎo)致ANR,全部是app應(yīng)用層的問(wèn)題。實(shí)際上,線上環(huán)境大部分ANR由系統(tǒng)原因?qū)е隆?/p>3.1 應(yīng)用層導(dǎo)致ANR(耗時(shí)操作)

a. 函數(shù)阻塞:如死循環(huán)、主線程IO、處理大數(shù)據(jù)

b. 鎖出錯(cuò):主線程等待子線程的鎖

c. 內(nèi)存緊張:系統(tǒng)分配給一個(gè)應(yīng)用的內(nèi)存是有上限的,長(zhǎng)期處于內(nèi)存緊張,會(huì)導(dǎo)致頻繁內(nèi)存交換,進(jìn)而導(dǎo)致應(yīng)用的一些操作超時(shí)

3.2 系統(tǒng)導(dǎo)致ANR

a. CPU被搶占:一般來(lái)說(shuō),前臺(tái)在玩游戲,可能會(huì)導(dǎo)致你的后臺(tái)廣播被搶占CPU

b. 系統(tǒng)服務(wù)無(wú)法及時(shí)響應(yīng):比如獲取系統(tǒng)聯(lián)系人等,系統(tǒng)的服務(wù)都是Binder機(jī)制,服務(wù)能力也是有限的,有可能系統(tǒng)服務(wù)長(zhǎng)時(shí)間不響應(yīng)導(dǎo)致ANR

c. 其他應(yīng)用占用的大量?jī)?nèi)存

四、分析日志

發(fā)生ANR的時(shí)候,系統(tǒng)會(huì)產(chǎn)生一份anr日志文件(手機(jī)的/data/anr 目錄下,文件名稱可能各廠商不一樣,業(yè)內(nèi)大多稱呼為trace文件),內(nèi)含如下幾項(xiàng)重要信息。

4.1 CPU 負(fù)載

Load: 2.62 / 2.55 / 2.25

CPU usage from 0ms to 1987ms later (2020-03-10 08:31:55.169 to 2020-03-10 08:32:17.156):

  41% 2080/system_server: 28% user + 12% kernel / faults: 76445 minor 180 major

  26% 9378/com.xiaomi.store: 20% user + 6.8% kernel / faults: 68408 minor 68 major

........省略N行.....

66% TOTAL: 20% user + 15% kernel + 28% iowait + 0.7% irq + 0.7% softirq

如上所示:

第一行:1、5、15 分鐘內(nèi)正在使用和等待使用CPU 的活動(dòng)進(jìn)程的平均數(shù) 第二行:表明負(fù)載信息抓取在ANR發(fā)生之后的0~1987ms。同時(shí)也指明了ANR的時(shí)間點(diǎn):2020-03-10 08:31:55.169 中間部分:各個(gè)進(jìn)程占用的CPU的詳細(xì)情況 最后一行:各個(gè)進(jìn)程合計(jì)占用的CPU信息。

名詞解釋:

a. user:用戶態(tài),kernel:內(nèi)核態(tài)

b. faults:內(nèi)存缺頁(yè),minor——輕微的,major——重度,需要從磁盤(pán)拿數(shù)據(jù)

c. iowait:IO使用(等待)占比

d. irq:硬中斷,softirq:軟中斷

注意:

iowait占比很高,意味著有很大可能,是io耗時(shí)導(dǎo)致ANR,具體進(jìn)一步查看有沒(méi)有進(jìn)程faults major比較多。 單進(jìn)程CPU的負(fù)載并不是以100%為上限,而是有幾個(gè)核,就有百分之幾百,如4核上限為400%。4.2 內(nèi)存信息

Total number of allocations 476778進(jìn)程創(chuàng)建到現(xiàn)在一共創(chuàng)建了多少對(duì)象

Total bytes allocated 52MB 進(jìn)程創(chuàng)建到現(xiàn)在一共申請(qǐng)了多少內(nèi)存

Total bytes freed 52MB 進(jìn)程創(chuàng)建到現(xiàn)在一共釋放了多少內(nèi)存

Free memory 777KB  不擴(kuò)展堆的情況下可用的內(nèi)存

Free memory until GC 777KBGC前的可用內(nèi)存

Free memory until OOME 383MBOOM之前的可用內(nèi)存

Total memory 當(dāng)前總內(nèi)存(已用+可用)

Max memory 384MB  進(jìn)程最多能申請(qǐng)的內(nèi)存

從含義可以得出結(jié)論:**Free memory until OOME**的值很小的時(shí)候,已經(jīng)處于內(nèi)存緊張狀態(tài)。應(yīng)用可能是占用了過(guò)多內(nèi)存。

另外,除了trace文件中有內(nèi)存信息,普通的eventlog日志中,也有內(nèi)存信息(不一定打印)

04-02 22:00:08.195  1531  1544 I am_meminfo: [350937088,41086976,492830720,427937792,291887104]

以上四個(gè)值分別指的是:

Cached Free, Zram, Kernel,Native

Cached+Free的內(nèi)存代表著當(dāng)前整個(gè)手機(jī)的可用內(nèi)存,如果值很小,意味著處于內(nèi)存緊張狀態(tài)。一般低內(nèi)存的判定閾值為:4G 內(nèi)存手機(jī)以下閥值:350MB,以上閥值則為:450MB

ps:如果ANR時(shí)間點(diǎn)前后,日志里有打印onTrimMemory,也可以作為內(nèi)存緊張的一個(gè)參考判斷

4.3 堆棧消息

堆棧信息是最重要的一個(gè)信息,展示了ANR發(fā)生的進(jìn)程當(dāng)前所有線程的狀態(tài)。

suspend all histogram:  Sum: 2.834s 99% C.I. 5.738us-7145.919us Avg: 607.155us Max: 41543us

DALVIK THREADS (248):

'main' prio=5 tid=1 Native

  | group='main' sCount=1 dsCount=0 flags=1 obj=0x74b17080 self=0x7bb7a14c00

  | sysTid=2080 nice=-2 cgrp=default sched=0/0 handle=0x7c3e82b548

  | state=S schedstat=( 757205342094 583547320723 2145008 ) utm=52002 stm=23718 core=5 HZ=100

  | stack=0x7fdc995000-0x7fdc997000 stackSize=8MB

  | held mutexes=

  kernel: __switch_to+0xb0/0xbc

  kernel: SyS_epoll_wait+0x288/0x364

  kernel: SyS_epoll_pwait+0xb0/0x124

  kernel: cpu_switch_to+0x38c/0x2258

  native: #00 pc 000000000007cd8c  /system/lib64/libc.so (__epoll_pwait+8)

  native: #01 pc 0000000000014d48  /system/lib64/libutils.so (android::Looper::pollInner(int)+148)

  native: #02 pc 0000000000014c18  /system/lib64/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+60)

  native: #03 pc 0000000000127474  /system/lib64/libandroid_runtime.so (android::android_os_MessageQueue_nativePollOnce(_JNIEnv*, _jobject*, long, int)+44)

  at android.os.MessageQueue.nativePollOnce(Native method)

  at android.os.MessageQueue.next(MessageQueue.java:330)

  at android.os.Looper.loop(Looper.java:169)

  at com.android.server.SystemServer.run(SystemServer.java:508)

  at com.android.server.SystemServer.main(SystemServer.java:340)

  at java.lang.reflect.Method.invoke(Native method)

  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:536)

  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:856)

  ........省略N行.....

  'OkHttp ConnectionPool' daemon prio=5 tid=251 TimedWaiting

  | group='main' sCount=1 dsCount=0 flags=1 obj=0x13daea90 self=0x7bad32b400

  | sysTid=29998 nice=0 cgrp=default sched=0/0 handle=0x7b7d2614f0

  | state=S schedstat=( 951407 137448 11 ) utm=0 stm=0 core=3 HZ=100

  | stack=0x7b7d15e000-0x7b7d160000 stackSize=1041KB

  | held mutexes=

  at java.lang.Object.wait(Native method)

  - waiting on <0x05e5732e> (a com.android.okhttp.ConnectionPool)

  at com.android.okhttp.ConnectionPool$1.run(ConnectionPool.java:103)

  - locked <0x05e5732e> (a com.android.okhttp.ConnectionPool)

  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)

  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)

  at java.lang.Thread.run(Thread.java:764)

如上日志所示,本文截圖了兩個(gè)線程信息,一個(gè)是主線程main,它的狀態(tài)是native。

另一個(gè)是OkHttp ConnectionPool,它的狀態(tài)是TimeWaiting。眾所周知,教科書(shū)上說(shuō)線程狀態(tài)有5種:新建、就緒、執(zhí)行、阻塞、死亡。而Java中的線程狀態(tài)有6種,6種狀態(tài)都定義在:java.lang.Thread.State中

全面解析Android之ANR日志

問(wèn)題來(lái)了,上述main線程的native是什么狀態(tài),哪來(lái)的?其實(shí)trace文件中的狀態(tài)是是CPP代碼中定義的狀態(tài),下面是一張對(duì)應(yīng)關(guān)系表。

全面解析Android之ANR日志

由此可知,main函數(shù)的native狀態(tài)是正在執(zhí)行JNI函數(shù)。堆棧信息是我們分析ANR的第一個(gè)重要的信息,一般來(lái)說(shuō):

main線程處于 BLOCK、WAITING、TIMEWAITING狀態(tài),那基本上是函數(shù)阻塞導(dǎo)致ANR;

如果main線程無(wú)異常,則應(yīng)該排查CPU負(fù)載和內(nèi)存環(huán)境。

五、典型案例分析5.1 主線程無(wú)卡頓,處于正常狀態(tài)堆棧

'main' prio=5 tid=1 Native

  | group='main' sCount=1 dsCount=0 flags=1 obj=0x74b38080 self=0x7ad9014c00

  | sysTid=23081 nice=0 cgrp=default sched=0/0 handle=0x7b5fdc5548

  | state=S schedstat=( 284838633 166738594 505 ) utm=21 stm=7 core=1 HZ=100

  | stack=0x7fc95da000-0x7fc95dc000 stackSize=8MB

  | held mutexes=

  kernel: __switch_to+0xb0/0xbc

  kernel: SyS_epoll_wait+0x288/0x364

  kernel: SyS_epoll_pwait+0xb0/0x124

  kernel: cpu_switch_to+0x38c/0x2258

  native: #00 pc 000000000007cd8c  /system/lib64/libc.so (__epoll_pwait+8)

  native: #01 pc 0000000000014d48  /system/lib64/libutils.so (android::Looper::pollInner(int)+148)

  native: #02 pc 0000000000014c18  /system/lib64/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+60)

  native: #03 pc 00000000001275f4  /system/lib64/libandroid_runtime.so (android::android_os_MessageQueue_nativePollOnce(_JNIEnv*, _jobject*, long, int)+44)

  at android.os.MessageQueue.nativePollOnce(Native method)

  at android.os.MessageQueue.next(MessageQueue.java:330)

  at android.os.Looper.loop(Looper.java:169)

  at android.app.ActivityThread.main(ActivityThread.java:7073)

  at java.lang.reflect.Method.invoke(Native method)

  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:536)

  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:876)

上述主線程堆棧就是一個(gè)很正常的空閑堆棧,表明主線程正在等待新的消息。

如果ANR日志里主線程是這樣一個(gè)狀態(tài),那可能有兩個(gè)原因:

該ANR是CPU搶占或內(nèi)存緊張等其他因素引起 這份ANR日志抓取的時(shí)候,主線程已經(jīng)恢復(fù)正常

遇到這種空閑堆棧,可以按照第3節(jié)的方法去分析CPU、內(nèi)存的情況。其次可以關(guān)注抓取日志的時(shí)間和ANR發(fā)生的時(shí)間是否相隔過(guò)久,時(shí)間過(guò)久這個(gè)堆棧就沒(méi)有分析意義了。

5.2 主線程執(zhí)行耗時(shí)操作

'main' prio=5 tid=1 Runnable

  | group='main' sCount=0 dsCount=0 flags=0 obj=0x72deb848 self=0x7748c10800

  | sysTid=8968 nice=-10 cgrp=default sched=0/0 handle=0x77cfa75ed0

  | state=R schedstat=( 24783612979 48520902 756 ) utm=2473 stm=5 core=5 HZ=100

  | stack=0x7fce68b000-0x7fce68d000 stackSize=8192KB

  | held mutexes= 'mutator lock'(shared held)

  at com.example.test.MainActivity$onCreate$2.onClick(MainActivity.kt:20)——關(guān)鍵行!!!

  at android.view.View.performClick(View.java:7187)

  at android.view.View.performClickInternal(View.java:7164)

  at android.view.View.access$3500(View.java:813)

  at android.view.View$PerformClick.run(View.java:27640)

  at android.os.Handler.handleCallback(Handler.java:883)

  at android.os.Handler.dispatchMessage(Handler.java:100)

  at android.os.Looper.loop(Looper.java:230)

  at android.app.ActivityThread.main(ActivityThread.java:7725)

  at java.lang.reflect.Method.invoke(Native method)

  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:526)

  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1034)

上述日志表明,主線程正處于執(zhí)行狀態(tài),看堆棧信息可知不是處于空閑狀態(tài),發(fā)生ANR是因?yàn)橐惶巆lick監(jiān)聽(tīng)函數(shù)里執(zhí)行了耗時(shí)操作。

5.3 主線程被鎖阻塞

'main' prio=5 tid=1 Blocked

  | group='main' sCount=1 dsCount=0 flags=1 obj=0x72deb848 self=0x7748c10800

  | sysTid=22838 nice=-10 cgrp=default sched=0/0 handle=0x77cfa75ed0

  | state=S schedstat=( 390366023 28399376 279 ) utm=34 stm=5 core=1 HZ=100

  | stack=0x7fce68b000-0x7fce68d000 stackSize=8192KB

  | held mutexes=

  at com.example.test.MainActivity$onCreate$1.onClick(MainActivity.kt:15)

  - waiting to lock <0x01aed1da> (a java.lang.Object) held by thread 3 ——————關(guān)鍵行!!!

  at android.view.View.performClick(View.java:7187)

  at android.view.View.performClickInternal(View.java:7164)

  at android.view.View.access$3500(View.java:813)

  at android.view.View$PerformClick.run(View.java:27640)

  at android.os.Handler.handleCallback(Handler.java:883)

  at android.os.Handler.dispatchMessage(Handler.java:100)

  at android.os.Looper.loop(Looper.java:230)

  at android.app.ActivityThread.main(ActivityThread.java:7725)

  at java.lang.reflect.Method.invoke(Native method)

  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:526)

  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1034)

  ........省略N行.....

  'WQW TEST' prio=5 tid=3 TimeWating

  | group='main' sCount=1 dsCount=0 flags=1 obj=0x12c44230 self=0x772f0ec000

  | sysTid=22938 nice=0 cgrp=default sched=0/0 handle=0x77391fbd50

  | state=S schedstat=( 274896 0 1 ) utm=0 stm=0 core=1 HZ=100

  | stack=0x77390f9000-0x77390fb000 stackSize=1039KB

  | held mutexes=

  at java.lang.Thread.sleep(Native method)

  - sleeping on <0x043831a6> (a java.lang.Object)

  at java.lang.Thread.sleep(Thread.java:440)

  - locked <0x043831a6> (a java.lang.Object)

  at java.lang.Thread.sleep(Thread.java:356)

  at com.example.test.MainActivity$onCreate$2$thread$1.run(MainActivity.kt:22)

  - locked <0x01aed1da> (a java.lang.Object)————————————————————關(guān)鍵行!!!

  at java.lang.Thread.run(Thread.java:919)

這是一個(gè)典型的主線程被鎖阻塞的例子;

waiting to lock <0x01aed1da> (a java.lang.Object) held by thread 3

其中等待的鎖是<0x01aed1da>,這個(gè)鎖的持有者是線程 3。進(jìn)一步搜索 “tid=3” 找到線程3, 發(fā)現(xiàn)它正在TimeWating。

那么ANR的原因找到了:線程3持有了一把鎖,并且自身長(zhǎng)時(shí)間不釋放,主線程等待這把鎖發(fā)生超時(shí)。在線上環(huán)境中,常見(jiàn)因鎖而ANR的場(chǎng)景是SharePreference寫(xiě)入。

5.4 CPU被搶占

CPU usage from 0ms to 10625ms later (2020-03-09 14:38:31.633 to 2020-03-09 14:38:42.257):

  543% 2045/com.alibaba.android.rimet: 54% user + 89% kernel / faults: 4608 minor 1 major ————關(guān)鍵行!!!

  99% 674/[email protected]: 81% user + 18% kernel / faults: 403 minor

  24% 32589/com.wang.test: 22% user + 1.4% kernel / faults: 7432 minor 1 major

  ........省略N行.....

如上日志,第二行是釘釘?shù)倪M(jìn)程,占據(jù)CPU高達(dá)543%,搶占了大部分CPU資源,因而導(dǎo)致發(fā)生ANR。

5.5內(nèi)存緊張導(dǎo)致ANR

如果有一份日志,CPU和堆棧都很正常(不貼出來(lái)了),仍舊發(fā)生ANR,考慮是內(nèi)存緊張。

從CPU第一行信息可以發(fā)現(xiàn),ANR的時(shí)間點(diǎn)是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)

接著去系統(tǒng)日志里搜索am_meminfo, 這個(gè)沒(méi)有搜索到。再次搜索onTrimMemory,果然發(fā)現(xiàn)了很多條記錄;

10-31 22:37:19.749 20733 20733 E Runtime : onTrimMemory level:80,pid:com.xxx.xxx:Launcher0

10-31 22:37:33.458 20733 20733 E Runtime : onTrimMemory level:80,pid:com.xxx.xxx:Launcher0

10-31 22:38:00.153 20733 20733 E Runtime : onTrimMemory level:80,pid:com.xxx.xxx:Launcher0

10-31 22:38:58.731 20733 20733 E Runtime : onTrimMemory level:80,pid:com.xxx.xxx:Launcher0

10-31 22:39:02.816 20733 20733 E Runtime : onTrimMemory level:80,pid:com.xxx.xxx:Launcher0

可以看出,在發(fā)生ANR的時(shí)間點(diǎn)前后,內(nèi)存都處于緊張狀態(tài),level等級(jí)是80,查看Android API 文檔;

/** * Level for {@link #onTrimMemory(int)}: the process is nearing the end * of the background LRU list, and if more memory isn’t found soon it will * be killed. */ static final int TRIM_MEMORY_COMPLETE = 80;

可知80這個(gè)等級(jí)是很嚴(yán)重的,應(yīng)用馬上就要被殺死,被殺死的這個(gè)應(yīng)用從名字可以看出來(lái)是桌面,連桌面都快要被殺死,那普通應(yīng)用能好到哪里去呢?

一般來(lái)說(shuō),發(fā)生內(nèi)存緊張,會(huì)導(dǎo)致多個(gè)應(yīng)用發(fā)生ANR,所以在日志中如果發(fā)現(xiàn)有多個(gè)應(yīng)用一起ANR了,可以初步判定,此ANR與你的應(yīng)用無(wú)關(guān)。

5.6 系統(tǒng)服務(wù)超時(shí)導(dǎo)致ANR

系統(tǒng)服務(wù)超時(shí)一般會(huì)包含BinderProxy.transactNative關(guān)鍵字,請(qǐng)看如下日志:

'main' prio=5 tid=1 Native

  | group='main' sCount=1 dsCount=0 flags=1 obj=0x727851e8 self=0x78d7060e00

  | sysTid=4894 nice=0 cgrp=default sched=0/0 handle=0x795cc1e9a8

  | state=S schedstat=( 8292806752 1621087524 7167 ) utm=707 stm=122 core=5 HZ=100

  | stack=0x7febb64000-0x7febb66000 stackSize=8MB

  | held mutexes=

  kernel: __switch_to+0x90/0xc4

  kernel: binder_thread_read+0xbd8/0x144c

  kernel: binder_ioctl_write_read.constprop.58+0x20c/0x348

  kernel: binder_ioctl+0x5d4/0x88c

  kernel: do_vfs_ioctl+0xb8/0xb1c

  kernel: SyS_ioctl+0x84/0x98

  kernel: cpu_switch_to+0x34c/0x22c0

  native: #00 pc 000000000007a2ac  /system/lib64/libc.so (__ioctl+4)

  native: #01 pc 00000000000276ec  /system/lib64/libc.so (ioctl+132)

  native: #02 pc 00000000000557d4  /system/lib64/libbinder.so (android::IPCThreadState::talkWithDriver(bool)+252)

  native: #03 pc 0000000000056494  /system/lib64/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+60)

  native: #04 pc 00000000000562d0  /system/lib64/libbinder.so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+216)

  native: #05 pc 000000000004ce1c  /system/lib64/libbinder.so (android::BpBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+72)

  native: #06 pc 00000000001281c8  /system/lib64/libandroid_runtime.so (???)

  native: #07 pc 0000000000947ed4  /system/framework/arm64/boot-framework.oat (Java_android_os_BinderProxy_transactNative__ILandroid_os_Parcel_2Landroid_os_Parcel_2I+196)

  at android.os.BinderProxy.transactNative(Native method) ————————————————關(guān)鍵行!!!

  at android.os.BinderProxy.transact(Binder.java:804)

  at android.net.IConnectivityManager$Stub$Proxy.getActiveNetworkInfo(IConnectivityManager.java:1204)—關(guān)鍵行!

  at android.net.ConnectivityManager.getActiveNetworkInfo(ConnectivityManager.java:800)

  at com.xiaomi.NetworkUtils.getNetworkInfo(NetworkUtils.java:2)

  at com.xiaomi.frameworkbase.utils.NetworkUtils.getNetWorkType(NetworkUtils.java:1)

  at com.xiaomi.frameworkbase.utils.NetworkUtils.isWifiConnected(NetworkUtils.java:1)

從堆棧可以看出獲取網(wǎng)絡(luò)信息發(fā)生了ANR:getActiveNetworkInfo。

系統(tǒng)的服務(wù)都是Binder機(jī)制(16個(gè)線程),服務(wù)能力也是有限的,有可能系統(tǒng)服務(wù)長(zhǎng)時(shí)間不響應(yīng)導(dǎo)致ANR。如果其他應(yīng)用占用了所有Binder線程,那么當(dāng)前應(yīng)用只能等待。

可進(jìn)一步搜索:blockUntilThreadAvailable關(guān)鍵字:

at android.os.Binder.blockUntilThreadAvailable(Native method)

如果有發(fā)現(xiàn)某個(gè)線程的堆棧,包含此字樣,可進(jìn)一步看其堆棧,確定是調(diào)用了什么系統(tǒng)服務(wù)。此類ANR也是屬于系統(tǒng)環(huán)境的問(wèn)題,如果某類型機(jī)器上頻繁發(fā)生此問(wèn)題,應(yīng)用層可以考慮規(guī)避策略。

以上就是全面解析Android之ANR日志的詳細(xì)內(nèi)容,更多關(guān)于Android ANR日志的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Android
相關(guān)文章:
主站蜘蛛池模板: 莫菁在线| 免费在线观看一区二区 | 成人国产精品一级毛片视频 | 黄色三级三级三级免费看 | 日韩中文字幕精品免费一区 | 牛牛a级毛片在线播放 | 日韩一卡二卡三卡 | 正在播放的国产a一片 | 亚洲六月丁香婷婷综合 | 搞黄视频免费 | 国产精品久久久久免费 | 亚洲精品区在线播放一区二区 | 欧美三级蜜桃2在线观看 | 婬荡少妇21p | 国产成人综合久久精品尤物 | 777久久成人影院 | 亚洲综合黄色 | 亚洲国产女人aaa毛片在线 | 欧美高清v | 欧美成人福利视频 | 亚洲国产成人久久精品影视 | 国产精品99久久久久久宅男 | 日韩在线国产精品 | 性欧美视频a毛片在线播放 性欧美视频在线观看 | 国产福利91精品一区二区三区 | 最新永久一路线二路线三路线 | 国产精品高清全国免费观看 | 欧美笫一页 | 97精品视频在线观看 | 精品一区二区三区高清免费不卡 | 日韩成人黄色片 | 免费一级a毛片在线搐放正片 | 久久久久久久九九九九 | 亚洲伦理一区二区 | 日韩特级毛片免费观看视频 | 精品视频在线观看视频免费视频 | 一区二区三区福利视频 | 麻豆小视频在线观看 | 国产精品高清一区二区三区 | 亚洲国产美女精品久久久久 | 尤物在线看 |