Android Anr 原理分析

2021-09-24 22:18:55 字數 2986 閱讀 8025

最近做了anr的一些研究,講述自己對anr流程的一些總結,本文主要從anr流程上來看不分析細節,需要細節的推薦

非常全面.

anrgoogle官方有比較清楚的解釋,同時指明了anr發生在主線程,這也隱含表示了anr是發生在應用內部的,而不是在系統中,所以我們的system_server 比較適合進行anr的排程,所以我們的anr都是在system_server監控與執行的

service anr

service的 anr 其實就是在system_server裡遠端呼叫應用service的每個生命週期函式前傳送乙個延遲時間是20s或者200s(由應用service的前後臺決定)的訊息service_timeout_msg,service的生命週期函式比如oncreate()在延遲訊息時間到達前呼叫結束就可以遠端呼叫system_server  remove()延遲訊息,這樣就取消了anr了.

如果service的生命週期函式執行時間超過20s或者200s,service_timeout_msg的訊息得到執行呼叫

servicetimeout() 最終執行ams裡的

廣播與contentprovide的anr與service大同小異,這裡不再講述了。input 的anr與這些都有點不同,同時是最複雜的

input的anr的策略主要是在inputdispatcher裡進行的,可以看

大家可以看到inputdispatcher是在native層的,它也是在system_server程序中,工作在inputdispatcherthread執行緒中,inputdispatcher主要進行按鍵事件的派發,所以正適合進行anr的排程

簡單的說inputdispatcher 內部有個threadloop,會不斷迴圈執行dispatchonce()來執行按鍵事件或者一些上一次迴圈存在佇列裡面的命令,當沒有事件時,執行緒會在等待狀態,等待事件喚醒或者根據給定的時間喚醒

一次正常的按鍵事件,需要找到應用的視窗findfocusedwindowtargetslocked(),向視窗派發按鍵,在找到視窗以後,會呼叫checkwindowreadyformoreinputlocked() 檢查視窗是否有能力再接收新的輸入事件,會有一系列的場景阻礙事件的繼續派發,它們就是是

anr reason

//當視窗暫停的情況,則保持等待

if(windowhandle->getinfo()->paused)

//當視窗連線未註冊,則保持等待

ssize_t connectionindex = getconnectionindexlocked(windowhandle->getinputchannel());

if (connectionindex < 0)

//當視窗連線已死亡,則保持等待

spconnection = mconnectionsbyfd.valueat(connectionindex);

if (connection->status != connection::status_normal) {

// 當視窗連線阻塞,則保持等待

if (connection->inputpublisherblocked)

//確保分發佇列,並沒有儲存過多事件

if (!connection->outboundqueue.isempty() || !connection->waitqueue.isempty())

我們來看anr具體怎麼發生的

我們首先要明確兩點

我們來看正常的按鍵流程

按鍵事件在通過checkwindowreadyformoreinputlocked() 的攔截後事件新增到outboundquque,當事件派發到應用,outboundquque刪除事件,同時事件加入到等待佇列waitqueue中,當應用處理完事件,又經過層層呼叫到inputdispatcher,事件從waitqueue中刪除,這就是一次完整的按鍵事件

來看一種anr情況

按鍵在t1按下通過checkwindowreadyformoreinputlocked() 的攔截派發到應用的視窗,這時outbondqueue.size =0

waitqueue.size = 1,應用程序卡住當按鍵keyup事件到來前都沒有處理按鍵事件,所以當keyup事件checkwindowreadyformoreinputlocked() 時,被outboundqueue.isempty()|| waitqueue.isempty() 攔截,記錄當前等待事件t2+5s,喚醒時間t2+5s,當t2+5s到達,執行anr

從上面流程看出anr在地二次事件才計算時間,那對於長按按鍵呢,這時候只有按下事件,發生anr嗎,事實時也有anr發生,原因是當長按時0.5s後系統模擬了第二次的按下事件,該事件與正常事件流程一致,如果應用視窗程序卡住沒有處理事件,也導致anr

我們再看看如果是keyup事件呢,如果在keyup事件派發的時候應用視窗程序卡住不處理,有anr嗎

從以上分析可看出沒有事件的情況下沒有anr發生的條件,在6.0系統實驗也的確不造成anr,大家可以自己試試,只有當下次按鍵事件過來才執行5s後anr的邏輯

Android anr的產生與分析

1 檢視android anr的出現 需要在開發者選項中設定了 顯示所有應用無響應 為後台應用顯示無響應anr對話方塊 2 檢視android anr的日誌 2位於 data anr 資料夾下面,trace檔案,我們可以通過anr產生的traces日誌檔案分析應用在 產生了anr,以此來有效解決應用...

Android ANR產生的原因及定位分析

典型的anr問題場景 1 ui執行緒存在耗時操作,例如ui執行緒中存在網路請求 資料庫操作或者檔案操作等。android 4.0以後,如果在ui執行緒進行網路操作會直接報異常 2 ui執行緒等待子執行緒釋放某個鎖,從而無法處理使用者輸入 3 耗時的動畫需要大量的計算工作,導致cpu負載過重 anr的...

android ANR處理方法

可能會存在這樣的情況,你寫的 通過了世界上所有的效能測試,但當使用者嘗試使用你的應用程式時,仍然讓使用者感到不爽。應用程式響應不夠靈敏的地方包括 反映遲鈍,掛起或凍結很長時間,或者需要花費很長的時間來處理輸入。一般說來,如果應用程式不能響應使用者輸入的話,系統會顯示乙個anr。例如,乙個應用程式阻塞...