欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android?ANR分析trace文件的產(chǎn)生流程詳情

 更新時(shí)間:2022年07月04日 15:15:02   作者:wx5e435a4343578  
這篇文章主要介紹了Android?ANR分析trace文件的產(chǎn)生流程詳情,文章圍繞主題展開(kāi)相詳細(xì)的內(nèi)容介紹,需要的朋友可以參考一下

前言

首先收集需要dump trace的進(jìn)程并給對(duì)應(yīng)進(jìn)程發(fā)送dump trace的信號(hào)

1.當(dāng)一些帶有超時(shí)機(jī)制的系統(tǒng)消息(如:Service的創(chuàng)建)判定超時(shí)后,會(huì)調(diào)用系統(tǒng)服務(wù)AMS接口,收集ANR相關(guān)信息并存檔(data/anr/trace, data/system/dropbox)

2.進(jìn)入到AMS中,AppError會(huì)先進(jìn)行篩選(1.當(dāng)前進(jìn)程正在進(jìn)行dump流程 2.已經(jīng)發(fā)生crash 3. 已經(jīng)被系統(tǒng)kill 4.系統(tǒng)是否正在關(guān)機(jī)等情況),如果都不符合,則認(rèn)為當(dāng)前進(jìn)程發(fā)生了anr。

3.接下來(lái)系統(tǒng)在判斷當(dāng)前ANR進(jìn)程對(duì)用戶是否可感知,然后開(kāi)始統(tǒng)計(jì)與該進(jìn)程由關(guān)聯(lián)的進(jìn)程,或者一些系統(tǒng)核心服務(wù)進(jìn)程的信息(例如與應(yīng)用交互的SurfaceFligner,System Server等系統(tǒng)進(jìn)程),如果這些系統(tǒng)服務(wù)進(jìn)程在響應(yīng)時(shí)被阻塞,那么將導(dǎo)致應(yīng)用進(jìn)程IPC通信過(guò)程被卡死。接著獲取其他系統(tǒng)核心進(jìn)程,因?yàn)檫@些服務(wù)進(jìn)程是init進(jìn)程直接創(chuàng)建的,并不在SystemServer或Zygote進(jìn)程管理范圍。 >firstPids隊(duì)列:第一個(gè)是ANR進(jìn)程,第二個(gè)是system_server,剩余是所有persistent進(jìn)程; Native隊(duì)列:是指/system/bin/目錄的mediaserver,sdcard 以及surfaceflinger進(jìn)程; lastPids隊(duì)列: 是指mLruProcesses中的不屬于firstPids的所有進(jìn)程。

4.在收集完第一步信息后,接下來(lái)便開(kāi)始統(tǒng)計(jì)各進(jìn)程本地的更多信息,如虛擬機(jī)信息,java線程狀態(tài)及堆棧。首先會(huì)彈出一個(gè)ANR的對(duì)話框,然后向UI線程發(fā)送SHOW_NOT_RESPONDING_MSG消息

5.當(dāng)UI線程收到該消息后,會(huì)調(diào)用dumpStackTraces函數(shù):

最重要的一點(diǎn):向目標(biāo)進(jìn)程發(fā)送SINAL_QUIT(進(jìn)程中的Signal Catcher會(huì)進(jìn)行阻塞檢測(cè)收集信息后面講),firstPids列表中的進(jìn)程, 兩個(gè)進(jìn)程之間會(huì)休眠200ms, 可見(jiàn)persistent進(jìn)程越多,則時(shí)間越長(zhǎng). top 5進(jìn)程的traces過(guò)程中, 同樣是間隔200ms, 另外進(jìn)程使用情況的收集也是比較耗時(shí).

總結(jié);

>將am_anr信息輸出到EventLog(分析anr問(wèn)題時(shí)先看該log) 獲取重要進(jìn)程的信息,java進(jìn)程的,和native的進(jìn)程 將ANR的Reason和CPU使用的情況輸出到main_log 在將CPU使用情況和進(jìn)程的trace文件信息,在保存到drpobox文件下 向收集到的進(jìn)程發(fā)送SINAL_QUIT信號(hào)。

接著分析最后一步向收集到的進(jìn)程發(fā)送信號(hào)

(Android5.0之前是dump用的SuspendAll線程,收集信息之后用ResumeAll恢復(fù)。在5.0之后采用的是checkPoint進(jìn)行dump信息)

發(fā)生ANR時(shí),systemServer進(jìn)程會(huì)執(zhí)行dumpStackTraces函數(shù),在該函數(shù)中發(fā)SIGQUIT信號(hào)給對(duì)應(yīng)的進(jìn)程(上面有分析到) 處于安全考慮,進(jìn)程之間是相互隔離的,即使系統(tǒng)進(jìn)程也無(wú)法獲取其他進(jìn)程的信息,所以要借助于IPC通信,將指令發(fā)送到目標(biāo)進(jìn)程,目標(biāo)進(jìn)程接收到消息后,協(xié)助完成自身進(jìn)程Dump信息并發(fā)送給系統(tǒng)進(jìn)程。Android P 流程:

1.一個(gè)進(jìn)程接收到了SIGQIUT信號(hào)的時(shí)候,SingaCatcher線程的WaitForSignal函數(shù)會(huì)返回接著會(huì)調(diào)用到HandlerSigQuit()函數(shù)。

2.hindleSigQuit()函數(shù)為:

3.DumpForSigQuit()函數(shù):

這是讀取的信息,但是什么時(shí)候去讀取呢(什么時(shí)候才能保證獲取到的卻是是需要的東西,例如GC信息,當(dāng)前分配了多少對(duì)象,這些打印一般都需要在suspend當(dāng)前進(jìn)程里面的所有的線程),接下來(lái)先分析這個(gè)suspend過(guò)程:

這個(gè)掛起SupendAll實(shí)在Thread_list.cc中實(shí)現(xiàn)的,他的作用就是用來(lái)suspend當(dāng)前進(jìn)程里面所有其他的線程(一般發(fā)生在GC,DumpForSigQuit等過(guò)程中)。SuspendAll過(guò)程實(shí)現(xiàn)最重要的就是ModifySupendCount(self,+1,false)這段語(yǔ)句他會(huì)修改對(duì)應(yīng)Thread對(duì)象的suspend引用計(jì)數(shù):

因?yàn)閭魅氲膁elta值是+1所以會(huì)先執(zhí)行AtmoicSetFlag()利用原子操作設(shè)置了KSuspendRequest標(biāo)志位,代表當(dāng)前這個(gè)線程有掛起請(qǐng)求。什么時(shí)候會(huì)進(jìn)行檢測(cè)這個(gè)標(biāo)志位呢?這里涉及到了checkPoint的知識(shí)點(diǎn)最后講解(在線程運(yùn)行中進(jìn)行上下文切換(例如java線程轉(zhuǎn)換為Native線程)時(shí)就會(huì)運(yùn)行CheckSuspend函數(shù),這個(gè)函數(shù)才是真正的把當(dāng)前線程suspend:

可以看到檢測(cè)到了KSuspendRequest標(biāo)記就會(huì)執(zhí)行FullSuspend函數(shù),KSuspendRequest標(biāo)志位是用來(lái)dump線程的堆棧的,分析完了SuspendAll之后,再繼續(xù)分析FullSuspendCheck函數(shù):

調(diào)用TransitionFromRunnableToSuspend()這個(gè)函數(shù)后,線程就進(jìn)入了KSuspended狀態(tài),然后在調(diào)用TransitionFromSuspendedToRunnablecpm函數(shù)從Suspend狀態(tài)切換到Runnable狀態(tài)的時(shí)候會(huì)阻塞在一個(gè)條件變量上,除非調(diào)用SuspendAll的線程接著又調(diào)用了ResumeAll()函數(shù),要不然這些線程就會(huì)一直被阻塞住。 4.現(xiàn)在就把SuspendAll的流程分析完了,但是dump線程堆棧的時(shí)候并不是在設(shè)置了掛起標(biāo)志位(KSuspendRequest)后執(zhí)行的,與他相關(guān)的是另外一個(gè)標(biāo)志位KCheckpointRequest,接下來(lái)看一下Thread_list的Dump函數(shù),這個(gè)函數(shù)會(huì)在Thread_list的DumpForSigQuit中會(huì)被調(diào)用到,也就是在Signal Cathcer線程處理SIGQUIT信號(hào)的過(guò)程中。

這個(gè)函數(shù)先創(chuàng)建了一個(gè)叫DumpCheckPoint對(duì)象checkpoint,然后調(diào)用了RunCheckpoint將這個(gè)對(duì)象傳入,這個(gè)函數(shù)會(huì)返回現(xiàn)在處于Runnable狀態(tài)的線程個(gè)數(shù),接著 調(diào)用了WaitForThreadsToRunThroughCheckpoint()等待這些處于Runnable的線程都執(zhí)行完DumpCheckpoint的Run函數(shù),如果等待超時(shí)就會(huì)報(bào)錯(cuò)。

接著分析RunCheckPoint函數(shù),先看前一部分:

對(duì)于處于Runnable狀態(tài)的線程執(zhí)行它的RequestCheckpoint函數(shù)會(huì)返回true,其他狀態(tài)的線程則會(huì)返回false。對(duì)于這些非Runnable狀態(tài)的線程就會(huì)像SuspendAll一樣會(huì)設(shè)置KSuspendRequest標(biāo)志位,后面狀態(tài)切換的時(shí)候就會(huì)檢查這個(gè)標(biāo)志位掛起。同事RunCheckPoint函數(shù)會(huì)把這些線程統(tǒng)計(jì)到suspend_count_modified_threads這個(gè)Vector變量中,在這個(gè)變量中的線程,Singal Catcher線程會(huì)主動(dòng)觸發(fā)他們的dump堆棧過(guò)程。接下來(lái)再看看這個(gè)RequestCheckpoint函數(shù)

最后一行設(shè)置kCheckpointRequest標(biāo)志位,在剛才線程切換運(yùn)行狀態(tài)時(shí)會(huì)執(zhí)行CheckSuspend函數(shù)在檢測(cè)kCheckpointRequest標(biāo)志位的時(shí)候會(huì)執(zhí)行RunCheckpointFunction函數(shù),接著會(huì)執(zhí)行這個(gè)checkpoints里面元素的run函數(shù):

(這個(gè)存儲(chǔ)的其實(shí)就是Thread中的RequestCheckpoint在這里不僅設(shè)置了標(biāo)志位還把參數(shù)設(shè)置為元素的值,這個(gè)參數(shù)就是Dump里面調(diào)用RunCheckpoint傳過(guò)來(lái)的,其實(shí)就是DumpCheckpoint)。 ,所以也就是執(zhí)行DumpCheckpoint的run函數(shù):

其實(shí)就是調(diào)用了Thread的Dump函數(shù),線程的java堆棧,Native堆棧和Kernel堆棧就是在這里打印的,剛才說(shuō)對(duì)于處于Runnable狀態(tài)的線程是通過(guò)調(diào)用他們的RequestCkeckPoint函數(shù),然后它們自己去dump當(dāng)前堆棧的,而那些不處于Runnable狀態(tài)的線程則是添加到了一個(gè)Vector的變量中,接著就分析RunCheckPoint函數(shù)的第二部分:

對(duì)于這些不是Runnable狀態(tài)的線程,他們可能不會(huì)主動(dòng)去調(diào)用Run函數(shù),所以只能有Signal Catcher線程去幫他們Dump,至于DumpCheckpoint的Run函數(shù)的功能和Runnable狀態(tài)的線程是一樣的,都是打印線程堆棧,并且最后修改引用計(jì)數(shù)讓這些線程在切換狀態(tài)時(shí)繼續(xù)運(yùn)行。

總結(jié):

>1.SingalCatcher線程接收到信號(hào)后,首先Dump當(dāng)前虛擬機(jī)有關(guān)信息(內(nèi)存狀態(tài)。對(duì)象,加載class,GC等相關(guān)信息) 2.接下來(lái)會(huì)設(shè)置每個(gè)線程的標(biāo)記為(check_point),和請(qǐng)求線程狀態(tài)(suspend)。當(dāng)線程運(yùn)行過(guò)程中進(jìn)行上下文切換時(shí),會(huì)檢查該標(biāo)記。如果發(fā)現(xiàn)有掛起請(qǐng)求,會(huì)將自己主動(dòng)掛起。等到所有線程都掛起之后,SingalCatcher線程開(kāi)始遍歷Dump各個(gè)線程的堆棧和線程數(shù)據(jù)后再喚醒線程。如果某個(gè)線程一直無(wú)法掛起導(dǎo)致超時(shí),那么本次Dump流程失敗拋出異常.

大致流程(Android5.0之前):

checkPoint:

先講解safePoint,對(duì)于ART編譯的代碼,可以定期輪詢當(dāng)前Runtime來(lái)確認(rèn)是否需要執(zhí)行某些特定代碼;可以認(rèn)為這些輪詢時(shí)的點(diǎn),就是safepoint;safepoint可以用來(lái)實(shí)現(xiàn)暫定一個(gè)java線程,也可以用來(lái)實(shí)現(xiàn)Checkpoint機(jī)制; 例: 當(dāng)正在執(zhí)行java代碼的線程A執(zhí)行到safepoint時(shí),會(huì)執(zhí)行CheckSuspend函數(shù),在發(fā)現(xiàn)當(dāng)前線程有 checkpoint request時(shí), 會(huì)在這個(gè)點(diǎn)執(zhí)行線程的CheckPoint函數(shù);如果發(fā)現(xiàn)當(dāng)前線程有suspend request時(shí),會(huì)進(jìn)行SuspendCheck,使得線程進(jìn)入Suspend狀態(tài)(暫停); 所以說(shuō),ART CheckPoint應(yīng)該是safepoint的一個(gè)功能實(shí)現(xiàn);

到此這篇關(guān)于Android ANR分析trace文件的產(chǎn)生流程詳情的文章就介紹到這了,更多相關(guān)Android ANR分析 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論