1. 程式人生 > >About ANR and OOM

About ANR and OOM

1. ANR

    1.1 什麼是ANR? ANR(Application Not Responding)

        在Android上,如果你的應用程式有一段時間響應不夠靈敏,系統會向用戶顯示一個對話方塊,這個對話方塊稱作應用程式無響應(ANR:ApplicationNotResponding)對話方塊。使用者可以選擇“等待”而讓程式繼續執行,也可以選擇“強制關閉”。所以一個流暢的合理的應用程式中不能出現anr,而讓使用者每次都要處理這個對話方塊。

          預設情況下,在android中Activity的最長執行時間是5秒,BroadcastReceiver的最長執行時間則是10秒 (廠商可以定製 這個時間)


    1.2 產生ANR的原因?

        1.在5秒內沒有響應輸入的事件。
        2.BroadcastReceiver在制定時間內完成

        具體點的原因: 1) IO操作耗時 。  2)資料庫操作複雜耗時。 3)主執行緒  非主執行緒 產生死鎖等待。 4)網路載入/圖片操作耗時。  5)硬體操作耗時。

                                     1) service binder 數量達到上限。 2)Service忙導致超時無響應。


    1.3 ANR是哪裡報出來的?

        ActivityManagerService 管理每個應用程式是否發生了ANR  。按照ANR發生的不同型別,細緻一點的說:

        1)KeyDispatchTimeout :每次dispatch 觸控事件的時候都會檢查當前接收事件的app是否 ready 去處理下一個事件,判斷的過程中會檢查是否發生了ANR。檢查的辦法是ActivityManagerService對比上次記錄的該pid的處理時間和當前時間的差值,是否大於系統規定的ANR超時時間。

        2)BroadcastTimeout:ActivityManagerService 管理著幾個broadcastQueue,這些broadcastQueue 管理者不同型別的broadcast。每個broadcast傳送給註冊的物件都有一個時間限制,BroadCastQueue會記錄每次傳送的開始時間以及結束時間,如果超過了ANR規定時間就會發生ANR。通過呼叫AMS中的AppNotResponding來彈出系統彈窗。

        3)ServiceTimeout:與KeyDispatchTimeout 類似。(沒有具體的看)

    1.4 如何盡力避免ANR?

        1)執行在主執行緒裡的任何方法都儘可能少做事情。特別是,Activity應該在它的關鍵生命週期方法(如onCreate()和onResume())裡儘可能少的去做建立操作。(可以採用重新開啟子執行緒的方式,然後使用Handler+Message的方式做一些操作,比如更新主執行緒中的ui等)

        2)應用程式應該避免在BroadcastReceiver裡做耗時的操作或計算。但不再是在子執行緒裡做這些任務(因為BroadcastReceiver的生命週期短),替代的是,如果響應Intent ,應用程式應該啟動一個Service。

        3)避免在IntentReceiver裡啟動一個Activity,因為它會建立一個新的畫面,並從當前使用者正在執行的程式上搶奪焦點。如果你的應用程式在響應Intent廣播時需要向用戶展示什麼,你應該使用Notification Manager來實現。

    1.5 出現ANR如何解決。

        解決ANR 主要通過 報錯log和Trace檔案分析解決。 從產生的原因入手。 具體方法可以參考一下: http://www.cnblogs.com/purediy/p/3225060.html


2. Crash

    Crash 包括很多情況,在進行系統debug的時候很容易區分。 例如JAVA層的Fatal 錯誤, 在log中會明確的打印出具體原因, 是陣列越界/未初始化變數/空指標等。又比如C/C++層的錯誤,會打印出相應的資訊,我們可以通過addr2line  來進行debug。 應用層的crash 是我們常說的FC。  system service 的crash 會導致 系統不能啟動/重啟等問題。

http://blog.csdn.net/god2469/article/details/9713395   (常見的SIG錯誤以及含義)


3. OOM

    OOM是指Out Of Memory。每個android應用單獨使用一個Dalvik虛擬機器,每個虛擬機器使用的堆記憶體是有限的,超過了限制就會引發oom錯誤。造成OOM幾乎都是自己的程式碼結構導致的不良。常見的原因:

   1)不恰當的使用static關鍵字。 儘量不要使用static儲存物件。

   2)內部類對Activity的引用。 內部類物件如果引用Activity物件,同時有很長的宣告週期的話會導致 Activity物件釋放不及時。

   3)Bitmap使用。 大量的bitmap會導致 程式包和執行時的記憶體消耗變大。

   4)遊標cursor的使用。 Cursor 物件用完應該及時關閉

   5)其他的內容。 我個人不能列舉所有的情況。其他的是我暫時沒有想到的 歡迎指教

文章中有一些引用的地方。不算原創。