最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

Android 如何監(jiān)控和解決ANR問題

2023-04-03 22:15 作者:程序員徐公  | 我要投稿

作者:Ryane_Lee
來源:https://blog.csdn.net/ljcITworld/article/details/104420422

一、ANR的定義

Android全稱是Application Not Response,即程序無響應(yīng)。ANR的直觀體驗是用戶在操作APP的過程中,感覺界面卡頓,如果
Android應(yīng)用的界面線程處于阻塞狀態(tài)的時間過長,會觸發(fā)“應(yīng)用無響應(yīng)”(ANR) 錯誤,如下圖所示,ANR 對話框會為用戶提供強行退出應(yīng)用的選項。

image

當(dāng)點擊了Close
app或者由于ANR引起了閃退之后,這時查看Logcat,一般可以發(fā)現(xiàn)ANR以及trace.txt等字樣,可以知道出現(xiàn)ANR主要原因是我們在主線程做了太多耗時操作,這時你可以選擇等待按鈕,等待應(yīng)用程序結(jié)束主線程的耗時操作,或者選擇確定按鈕,結(jié)束這個應(yīng)用程序,ANR對于一個應(yīng)用來說是不能承受之痛,其影響并不比應(yīng)用發(fā)生Crash小。

二、ANR類型

出現(xiàn)ANR的一般有以下幾種類型:

  • KeyDispatchTimeOut :最常見的一種類型,原因是View的按鍵事件或者觸摸事件在特定的時間(5秒)內(nèi)無法得到響應(yīng)。

  • BroadcaseTimeOut:原因是BroadcastReceiver的onReceiver()函數(shù)運行在主線程中,在特定的時間(10秒)內(nèi)無法完成處理。

  • ServiceTimeOut:比較少出現(xiàn)的一種類型,原因是Service的各個生命周期函數(shù)在特定時間(20秒)內(nèi)無法完成處理。

  • ContentProviderTimeout:ContentProvider在10S內(nèi)無法完成處理。

三、ANR原因

從應(yīng)用的角度上來講,它的原因可以歸結(jié)為以下幾種:

  • 應(yīng)用在主線程上非常緩慢地執(zhí)行涉及 I/O 的操作。

  • 應(yīng)用在主線程上進(jìn)行長時間的計算。

  • 主線程在對另一個進(jìn)程進(jìn)行同步 binder 調(diào)用,而后者需要很長時間才能返回。

  • 主線程處于阻塞狀態(tài),等待子線程的長時間耗時操作完成。

  • 主線程在進(jìn)程中或通過 binder 調(diào)用與另一個線程之間發(fā)生死鎖。主線程不只是在等待長操作執(zhí)行完畢,而且處于死鎖狀態(tài)。

三、如何檢測和診斷ANR問題

1、開發(fā)中檢測ANR

  • StrictMode(嚴(yán)格模式)

開發(fā)中由于個人原因,多多少少都會可能寫出造成ANR的代碼,要想在開發(fā)中及時發(fā)現(xiàn)問題,可以使用StrictMode有助于您在開發(fā)應(yīng)用時發(fā)現(xiàn)主線程上的意外
I/O 操作。

>

嚴(yán)苛模式是一個避免你不小心把網(wǎng)絡(luò)或者IO操作放在UI線程操作的開發(fā)工具,從而實現(xiàn)避免ANR。使用嚴(yán)苛模式,系統(tǒng)檢測出主線程違例的情況會做出相應(yīng)的反應(yīng),如日志打印,屏幕閃爍(需要在開發(fā)者選項里面打開啟用嚴(yán)格模式)等。

  • 啟用后臺 ANR 對話框

只有在設(shè)備的開發(fā)者選項中啟用了顯示所有 ANR 時,Android 才會針對花費過長時間處理廣播消息的應(yīng)用顯示 ANR
對話框。我們可以通過打開這個選項,在開發(fā)中及早發(fā)現(xiàn)相關(guān)問題。

  • TraceView

TraceView 是 Android SDK 中內(nèi)置的一個工具,它可以加載 trace
文件,用圖形的形式展示代碼的執(zhí)行時間、次數(shù)及調(diào)用棧,便于我們分析。(注意:Android Studio3.2之后已經(jīng)棄用)

  • CPU Profiler

Android Studio3.2之后,CPU
Profiler替代了TraceView,我們可以通過在通過記錄應(yīng)用交互過程獲取相關(guān)方法執(zhí)行順序和耗時圖,從而分析哪些方法耗時過長導(dǎo)致ANR。

2、線上ANR數(shù)據(jù)收集

在我們?nèi)粘i_發(fā)中經(jīng)常遇到的ANR問題都是線上用戶使用時發(fā)現(xiàn)的ANR問題,如果是我們開發(fā)中就已經(jīng)發(fā)現(xiàn),那是非常好解決的,只需要聚焦于新增代碼塊即可,但是如果是針對線上版本,那么我們就需要對線上數(shù)據(jù)進(jìn)行監(jiān)控,很多公司都會自主研發(fā)APM系統(tǒng),或者是借用第三方的,抑或使用Google官方的,都是可以統(tǒng)計到ANR的數(shù)據(jù)。其實有時候發(fā)現(xiàn)站在巨人的肩膀上去做一些事情,也許效率會更高,以下是一些常用的ANR數(shù)據(jù)收集工具:

  • 國外

    • Google vitals:Google Play自帶的性能統(tǒng)計工具。

    • Firebase Crashlytics:Google Cloud Platform為應(yīng)用開發(fā)者們提供的實時性能分析系統(tǒng)。

    • ACRA:在Goolge Play上有2.68%實用率的ACRA庫。

  • 國內(nèi)

    • Bugly:騰訊Bugly項目組推出移動應(yīng)用崩潰監(jiān)控分析平臺,提供崩潰、腳本錯誤、ANR(Android)/卡頓(iOS)問題等監(jiān)控分析服務(wù)。

    • xCrash:愛奇藝開源的一個性能監(jiān)控的SDK。

    • Umeng:國內(nèi)移動統(tǒng)計分析服務(wù)平臺,提供統(tǒng)計分析、更新、分享、推送等服務(wù),其中,錯誤分析也是在統(tǒng)計分析的基礎(chǔ)上添加。

    • Testin:國內(nèi)云測平臺,服務(wù)升級后,提供云測,APM服務(wù)(包括性能監(jiān)控,錯誤上報等),眾測等服務(wù)。

三、如何解決問題

無論我們通過線上還是開發(fā)中發(fā)現(xiàn)了ANR問題,我們都需要思考怎么去解決。

1、修改主線程上耗時的代碼

通過TraceView或者CPU Profiler可以找到應(yīng)用中主線程忙碌時間超過5s的位置,然后把此處代碼移到子線程操作。如一些網(wǎng)絡(luò)操作、耗時計算等。

2、鎖的競爭導(dǎo)致堵塞

如果主線程參與鎖的競爭,有可能會導(dǎo)致主線程持續(xù)等待鎖而造成堵塞的問題,從而引發(fā)ANR。所以最好還是避免主線程出現(xiàn)競爭鎖的情況。

3、死鎖

如果某資源被另一個線程所持有,而該線程又在等待主線程的資源,就會陷入死鎖情況導(dǎo)致ANR。

4、廣播接收器執(zhí)行速度慢

如在廣播接收器的onReceive()執(zhí)行了長時間的耗時操作,就會可能導(dǎo)致ANR,所以應(yīng)該把耗時操作放到子線程操作。

四、如何實現(xiàn)ANR監(jiān)控

站在巨人的肩膀固然好,但是如果能夠自己變成巨人那就更好了,所以作為一個有追求的開發(fā)者,我們當(dāng)然要思考如何監(jiān)控APP的ANR問題。

目前流行的ANR檢測方案有開源的BlockCanary 、ANR-WatchDog、SafeLooper,xCrash,
還有根據(jù)谷歌原生系統(tǒng)接口監(jiān)測的方案:FileObserver。

1、BlockCanary

BlockCanary是Android平臺上的一個輕量的,非侵入式的性能監(jiān)控組件,可以在使用應(yīng)用的時候檢測主線程上的各種卡頓問題,并可通過組件提供的各種信息分析出原因并進(jìn)行修復(fù)。

原理:

  • (1) 在Looper里面的loop方法里面有一個Printer打印日志,它在每個Message處理的前后被調(diào)用,而如果主線程卡住了,就是dispatchMessage里卡住了。

    public static void loop() { // .... ¨K24K

  • (2) 每個線程只有一個Looper,而只要重新設(shè)置主線程Looper里面的Printer即可重寫println方法,然后在這里面進(jìn)行前后兩次消息處理的時間差,從而計算是否有發(fā)生ANR。

    ?//?創(chuàng)建自定義Printer
    ????...
    ????@Override
    ????public?void?println(String?x)?{
    ????????if?(!mStartedPrinting)?{
    ????????????mStartTimeMillis?=?System.currentTimeMillis();
    ????????????mStartThreadTimeMillis?=?SystemClock.currentThreadTimeMillis();
    ????????????mStartedPrinting?=?true;
    ????????}?else?{
    ????????????final?long?endTime?=?System.currentTimeMillis();
    ????????????mStartedPrinting?=?false;
    ????????????if?(isBlock(endTime))?{
    ????????????????notifyBlockEvent(endTime);
    ????????????}
    ????????}
    ????}private?boolean?isBlock(long?endTime)?{
    ????return?endTime?-?mStartTimeMillis?>?mBlockThresholdMillis;
    }
    ...
  • (3)設(shè)置自定義Printer到主線程Looper

    ????????Looper.getMainLooper().setMessageLogging(mainLooperPrinter);
  • 優(yōu)點:靈活配置可監(jiān)控常見APP應(yīng)用性能也可作為一部分場景的ANR監(jiān)測,并且可以準(zhǔn)確定位ANR和耗時調(diào)用棧。

  • 缺點:

    • (1) 谷歌已經(jīng)明確標(biāo)注This must be in a local variable, in case a UI event sets the logger這個looger對象是可以被更改的,已經(jīng)有開發(fā)者遇到在使用WebView時logger被set為Null導(dǎo)致BlockCanary失效,只能讓BlockCanary在WebView初始化之后調(diào)用start。

    • (2) 如果dispatchMessage執(zhí)行的非常久是無法觸發(fā)BlockCanary的邏輯。

    • (3) 在Printer輸出之前,有一段代碼queue.next()也會可能發(fā)生ANR,從而造成無法監(jiān)控到ANR。

    • (4) 無法監(jiān)控CPU資源緊張造成系統(tǒng)卡頓無法響應(yīng)的ANR。

2、ANR-WatchDog

ANR-WatchDog是參考Android
WatchDog機制,起了個單獨線程向主線程發(fā)送一個變量+1的操作,然后休眠一定時間閾值(閾值可自定義,例如5s),休眠過后再判斷變量是否已經(jīng)+1,如果未完成則ANR告警。在GP上有有2.68%實用率的ACRA庫也推薦使用這種方式。

  • 原理:如下圖所示。

image
  • 優(yōu)點:

    • (1) 兼容性好,無需適配機型。

    • (2) 無需改動APP邏輯代碼,非侵入性。

    • (3) 性能影響不大。

  • 缺點:

    • (1) 無法保證能捕獲所有ANR,對閾值設(shè)置影響捕獲概率。如時間過長,中間發(fā)生的ANR則可能被遺漏掉。

3、SafeLooper

SafeLooper是一個第三方開源的庫,主要用于捕獲未知異常,避免出現(xiàn)ANR彈窗,從而在捕獲到異常時獲取ANR信息。

  • 原理:SafeLooper其實就是一個Runnable,啟動后把這個SafeLooper(消息)post到主線程,并且會輪訓(xùn)主線程的消息隊列,通過反射把新消息進(jìn)行處理,然后判斷新消息的處理過程是否會出現(xiàn)ANR導(dǎo)致的異常,如果是就將其捕獲,并把異常信息通過uncaughtException回調(diào)給用戶進(jìn)行處理。主要流程如下圖所示。

image
  • 優(yōu)點:使用AOP思想進(jìn)行異常捕獲的思想值得借鑒。

  • 缺點:使用反射會影響性能。

4、FileObserver

通過復(fù)現(xiàn)ANR場景,可以發(fā)現(xiàn)/data/anr文件夾會伴隨ANR發(fā)生而變化,所以可以通過監(jiān)聽/data/anr目錄下是否有文件寫入,如果有的話就認(rèn)為發(fā)生了ANR,像Bugly對ANR的監(jiān)控就是用這種方法來實現(xiàn)的。

  • 原理:自定義FileObserver監(jiān)聽/data/anr目錄下文件是否有新增".tarce"結(jié)尾的文件,如果有則認(rèn)為發(fā)生ANR,并導(dǎo)出trace文件,注意如果當(dāng)多個APP同時發(fā)生ANR,里面會有多個trace文件,需要對包名時間等進(jìn)行過濾。

  • 優(yōu)點:

    • (1) 基于原生接口調(diào)用,時機和內(nèi)容準(zhǔn)確。

    • (2) 無性能問題,實現(xiàn)簡單。

  • 缺點:

    • (1) /data/anr目錄可能不會在發(fā)生ANR時馬上寫入文件,可能會發(fā)生滯后,從而導(dǎo)致收集到的trace文件和線程信息不準(zhǔn)確。

5、xCrash

xCrash是愛奇藝開源的一個性能監(jiān)控SDK,它的實現(xiàn)方案和以上四種不太一樣,它是通過監(jiān)控系統(tǒng)的信號量的變化,從而確定是否發(fā)生了ANR,然后再整理輸出Tombstone文件。由于我對系統(tǒng)信號量了解不多,這里就貼出官方文檔的原理圖,歡迎了解的大神補充。

image

五、相關(guān)參考文章

  • BlockCanary原理分析

  • Qtest測試之道 Android ANR監(jiān)測方案解析

  • Android官方文檔-ANR


Android 如何監(jiān)控和解決ANR問題的評論 (共 條)

分享到微博請遵守國家法律
嘉祥县| 白山市| 射洪县| 万源市| 阿克| 新余市| 武汉市| 曲靖市| 邢台市| 西城区| 陆河县| 孟连| 成安县| 柏乡县| 泽普县| 白河县| 竹溪县| 阳谷县| 曲阳县| 岳西县| 察雅县| 嘉善县| 白山市| 昆明市| 武邑县| 松阳县| 来宾市| 宁陕县| 那曲县| 建宁县| 河池市| 湟源县| 伽师县| 漳平市| 曲阜市| 龙门县| 贵港市| 海兴县| 宜丰县| 宜宾县| 浮梁县|