Android異常之ANR

什麼是ANR

        ANR是Android中一個比較有代表性的異常,它的英文全稱是Application Not Responding,就是應用無響應的意思。Android開發中如果主線程(UI線程)在規定的時間內沒有處理完相應的工作就會發生ANR。ANR的直觀感受就是操作應用的過程中明顯的卡頓,主要的原因是在主線程中進行了太多的耗時操作。


ANR產生的原因

        當應用的主線程的響應超時纔會引發ANR,那麼產生響應超時的原因可分爲兩種,第一種是當前事件沒有機會得到處理,第二種是當前事件正在處理,但由於耗時太長沒能及時完成任務。

ANR出現的幾種情況

        本質上講產生ANR的原因分三種,對應着Activity/View、BroadcastReceiver、Service;

        keyDispatchTimeOut
        這是最典型也是最常見的一種類型,原因就是View的點擊事件或觸摸事件在特定的時間(5s)內沒有得到響應;

        BroadcastTimeOut
        BroadcastReceiver的onReceiver()函數運行在主線程中,在特定的時間(10s)內沒有完成處理;

        ServiceTimeOut
        比較少出現的一種類型,Service的各個生命週期函數在特定時間(20s)內無法得到處理引起;

造成ANR問題的原因(產生場景)

        1.主線程在做一些耗時操作,例如在主線程中進行網絡請求、數據庫操作或者文件操作可能會導致UI線程無法及時處理用戶的輸入信息;

        2.主線程被其他線程鎖。應用程序在UI線程等待子線程釋放某個鎖,導致無法處理用戶的輸入;;

        3.CPU被其他進程佔用,該進程沒被分配到足夠的cpu資源。例如耗時的動畫需要大量的計算工作導致CPU負載過重;;

        發生ANR後判斷產生原因很關鍵,到底是因爲主線程進行了耗時操作、主線程被其他線程鎖還是CPU被其他進程佔用,該進程沒被分配到足夠的CPU資源。我們需要從這些角度判斷引起異常的原因然後針對性處理。


ANR的定位和分析

ANR定位

        應用發生ANR的時候系統會收集ANR相關的信息內容提供給開發者用來處理問題。
        在Logcat中有ANR的相關信息,收集ANR的CPU的使用情況還有trace信息,也就是當前各個線程執行情況。
        trace文件保存在Android應用目錄/data/anr/traces.txt中,ANR進程打印出的Log信息也有一定的參考價值。


ANR分析

        1.從log中找到ANR發生的信息;
        2.在該條log之後會有CPU usage的信息,表明了CPU在ANR前後的用量,從各種CPU Usage信息中分析;
        (1)如果某些進程的CPU佔用百分比較高,發生ANR的進程CPU佔用爲0%或非常低,則認爲CPU資源被佔用,進程沒有被分配足夠的資源,從而發生了ANR。這種情況多數可以認爲是系統狀態的問題,並不是由本應用造成。
        (2)如果發生ANR的進程CPU佔用比較高,很大可能是因爲應用內一些代碼不合理消耗掉了CPU資源,例如出現了死循環或者後臺有許多線程執行任務等原因。
        (3)如果CPU總用量不高,該進程和其他進程的佔用過高,這有一定概率是由於某些主線程的操作就是耗時過長,或者由於主進程被鎖造成的。
        3.確定問題需要進一步分析trace文件,該文件記錄了發生ANR前後該進程的各個線程的stack,特別需要注意的是主線程的stack;
        (1)主線程是running或者native而對應的棧對應了我們應用中的函數,則很有可能就是執行該函數的時候發生了超時;
        (2)主線程被block非常明顯的線程被鎖,這時候可以看是被哪個線程鎖了,考慮優化代碼。如果是死鎖問題就需要及時解決。
        (3)由於抓trace的時刻有可能耗時操作已經執行完了,這時候trace就沒什麼用了,這種情況很可能是由於進程的其他線程消耗掉了CPU的資源,這就需要分析其他線程的trace以及ANR前後該進程自己輸出的log了。



降低ANR產生概率

        1.不在主線程(UI線程)進行耗時操作;
        2.不在BroadcastReceiver的onReceiver()方法中進行耗時操作;
        3.各個組件的聲明周期函數都不應該有太耗時的操作;
        4.儘量避免主線程被鎖的情況,在一些同步的操作主線程有可能被鎖,需要等待其他線程釋放響應鎖才能繼續執行,這樣會一定的ANR風險,對於這種情況有時也可以用異步線程來執行響應的邏輯。另外要避免死鎖的發生



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章