Android ANR監測方案解析

 

簡介

ANR(Application Not Responding),應用程序無響應,會嚴重影響用戶體驗。作爲測試開發人員更深入的理解ANR原理,可以更好的針對各類卡頓性能問題制定對應的監控策略。本文簡單總結了Android系統的ANR監測與現有的監測方案的原理對比。

ANR的觸發條件

ANR的本質是一個性能問題,即主線程中的耗時操作造成主線程堵塞,導致應用失去響應能力。常見的超時時限:

Service與Bradcast只會打印trace信息,不會提示用戶ANR彈窗,大部分可感知的ANR都是由於InputEvent。

Android對ANR的監控機制

Android應用程序是通過消息來驅動的,Android某種意義上也可以說成是一個以消息驅動的系統,UI、事件、生命週期都和消息處理機制息息相關。Android的ANR監測方案也是一樣,大部分就是利用了Android的消息機制。

InputEvent的ANR與上圖有些許不同,是在Native監控,但同樣會堵塞主線程的消息隊列,後面會講到一部分監測場景。

應用ANR檢測方案

目前流行的ANR檢測方案有開源的BlockCanary 、ANR-WatchDog、SafeLooper, 還有根據谷歌原生系統接口監測的方案:FileObserver。下面就針對這四種方案根據場景解析對比。

BlockCanary

BlockCanary是國內開發者markzhai開發的一款非侵入式的輕量性能監控組件,在Github上有接近4000 star。原理巧妙的利用了Android原生Looper.loop中的一個log打印邏輯。

這個log打印邏輯正是在Message消息分發前後,大部分的性能卡頓問題都是在這裏發生的,監控這兩個邏輯之間的時間差就可以得到當前主線程的卡頓狀態,如果超時則獲取trace信息並上報。具體實現:

優點:

靈活配置可監控常見APP應用性能也可作爲一部分場景的ANR監測,並且可以準確定位ANR和耗時調用棧。

缺點:

但BlockCanary應用在ANR監控上有幾個比較嚴重的問題:

  1. 谷歌已經明確標註This must be in a local variable, in case a UI event sets the logger這個looger對象是可以被更改的,已經有開發者遇到在使用WebView時logger被set爲Null導致BlockCanary失效,只能讓BlockCanary在WebView初始化之後調用start。
  2. 如果dispatchMessage執行的非常久是無法觸發BlockCanary的邏輯。
  3. 谷歌在Looper中還有一個標註

這裏的queue.next是可能block的,場景就是文章開始提到的InputEvent。此處block同樣會觸發ANR,但BlockCanary同樣無法適用的。一個例子可以驗證下:

在Activity中重寫dispatchTouchEvent和dispatchKeyEvent,模擬耗時操作,彈出ANR告警,但BlockCanary沒有任何反應,查看調用棧。

會看到InputEvent在queue.next中block,不會繼續執行dispatchMessage,而是從native回調給InputEventReceiver.dispatchInputEvent處理分發,所以BlockCanary也就無法監控到這類ANR。

4.無法監控CPU資源緊張造成系統卡頓,無法響應的ANR。

ANR-WatchDog

ANR-WatchDog是參考Android WatchDog機制(com.android.server.WatchDog.java)起個單獨線程向主線程發送一個變量+1操作,自我休眠自定義ANR的閾值,休眠過後判斷變量是否+1完成,如果未完成則告警。

優點:

  1. 兼容性好,各個機型版本通用
  2. 無需修改APP邏輯代碼,非侵入式
  3. 邏輯簡單,性能影響不大

缺點:

無法保證能捕捉所有ANR,對閾值的設置直接影響捕獲概率。如圖:

如果對線程的堵塞大於10s則設置監控閾值5s能捕獲所有ANR,堵塞時間在5s~10s,則可能出現無法捕獲場景。

SafeLooper

SafeLooper是個比較新奇的思路,本身就是一個堵塞的消息,在自己內部進行消息的處理,通過反射接管主線程Looper的功能。

此方案使用反射進行message管理會有很大的性能損耗,但可以自由定製,這種AOP的思想是可以借鑑的。

FileObserver

有ANR的流程就可以知道/data/anr文件夾的變化代表着ANR的發生,AMS在dumpStackTrace方法中給了我們一些提示。

按照這個思路,當ANR發生的時候,我們是可以通過監聽該文件的寫入情況來判斷是否發生了ANR,看起來這是一個不錯的時機。需要注意的是,所有應用發生ANR的時候都會進行回調,因此需要做一些過濾與判斷,如包名、進程號等。ANR生成的trace如圖:

優點:

  1. 基於原生接口調用,時機和內容準確。
  2. 無性能問題實現簡單

缺點:

最大的困難是兼容性問題,這個方案受限於Android系統的SELinux機制,5.0以後基本已經使低權限應用無法監聽到trace文件了,但是可以在開發內測階段通過root手機修改app對應的te文件提權進行監控。Android 7.1.1版本的測試截圖

可以看到很多應用都嘗試監聽ANR文件,但是都被權限拒絕,屬於不受信任應用。

SELinux(或SEAndroid)將app劃分爲主要三種類型(根據user不同,也有其他的domain類型):

  1. untrusted_app:第三方app,沒有android平臺簽名,沒有system權限
  2. platform_app:有android平臺簽名,沒有system權限
  3. system_app:有android平臺簽名和system權限

從上面劃分,權限等級,理論上:untrusted_app < platform_app < system_app

總結

本文彙總了目前主流的ANR監測方案的原理和實現,目前能瞭解到的方案並不太多,在Goolge Play上有2.68%實用率的ACRA庫也只是推薦了WatchDog方式。建議 FileObserver和watchDog組合使用,能覆蓋絕大部分的機型和ANR異常。如果其他同學有更好的建議和方案歡迎交流,共同進步。

參考

https://github.com/ACRA/acra

https://github.com/markzhai/AndroidPerformanceMonitor

https://github.com/SalomonBrys/ANR-WatchDog、

http://gityuan.com/2016/07/02/android-anr/

http://blog.csdn.net/zhudaozhuan/article/details/50964832

 

 

 

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