一文教你輕鬆搞定ANR異常捕獲與分析方法

語言: CN / TW / HK

簡介: 選擇一款有超強捕獲能力的專業產品,對於開發者定位和修復穩定性問題至關重要。友盟+U-APM SDK集成了UC 核心團隊強大的技術及友盟+超強的錯誤捕獲能力,通過數萬次捕獲實踐中積累了豐富經驗,在產品、效能和研發能力上都極大保障了開發者定位和修復穩定性問題的超強效率。

1. ANR 產生原理

關於 ANR 的觸發原因,Android 官方開發者文件中 “What Triggers ANR?” 有介紹,如下:

Generally, the system displays an ANR if an application cannot respond to user input. For example, if an application blocks on some I/O operation (frequently a network access) on the UI thread so the system can't process incoming user input events. Or perhaps the app spends too much time building an elaborate in-memory structure or computing the next move in a game on the UI thread. It's always important to make sure these computations are efficient, but even the most efficient code still takes time to run......

即,常見的有如下兩種情況會產生 ANR:

輸入事件(例如按鍵或螢幕輕觸事件等)在 5 秒內沒有響應;

BroadcastReceiver 在 10 秒內沒有執行完成。

結合 Android 相關原始碼分析可知,輸入事件的 ANR 檢測是基於輸入事件本身驅動的,系統要求在 App程序中處理完成每個輸入事件後,通知系統程序事件處理完畢,以此判斷 App是否無響應。

要產生 ANR,至少得有兩個輸入事件,場景如下:

第一個輸入事件產生,系統將其傳送給使用者當前操作的 App;

系統收到第二個事件,發現當前距第一個輸入事件傳送時間超過 0.5s 仍未處理完畢,則設定一個定時器,5s 後觸發;

5s 之後,若系統發現第一個輸入事件仍然沒有迴應時,則觸發 ANR,啟用 App 中的 Signal Cather 執行緒生成 traces.txt,然後彈出 ANR 對話方塊,告知使用者 App 無響應。

也就是說,要產生 ANR,第一個輸入事件必需在 5.5s 以上沒有被處理完成並反饋回系統;並且要有第二個輸入事件產生。如果沒有第二個輸入事件,即便第一個輸入事件執行了 60s 或更長時間,也是不會產生 ANR 的。

2. ANR 日誌生成原理

系統的 system_server 程序在檢測到 App 出現 ANR 後,會向出現 ANR 的程序傳送 SIGQUIT (signal 3) 訊號。正常情況下,系統的 libart.so 會收到該訊號,並呼叫 Java 虛擬機器的 dump 方法生成 traces。

以友盟+的 U-APM 應用效能監控平臺為例,整合SDK 後,SDK 會攔截 SIGQUIT。在出現 ANR 時,libcrashsdk.so 會優先收到訊號,並生成 traces 和 ANR 日誌。在 SDK 處理完訊號後,會將訊號繼續傳遞給系統的 libart.so,讓系統生成 ANR traces.txt。

如下圖,紅色線為 U-APM SDK 處理 ANR 訊號和生成 ANR 日誌的流程,紫色線為系統生成 ANR traces.txt 的流程。

圖片1.png

U-APM SDK ANR 捕獲原理

其中,SDK 生成 traces 時,使用的是 libart.so 中的 dump 方法,生成的內容與系統原生的基本一致。並且,U-APM SDK 在呼叫 dump 方法時進行了優化,dump 速度較系統生成原生 traces 的速度顯著提升,有效地避免了可能因生成 traces 時間過長,而被 system_server 使用 SIGKILL (signal 9) 再次強殺。

在獲取所有執行緒的 traces 資訊後,生成完整的 ANR 日誌,還會提供獲取觸發 ANR 的原因、手機中 TOP 程序 CPU 使用率、ANR 程序中 TOP 執行緒 CPU 使用率、CPU 各核心處理時間分佈情況、磁碟 IO 操作等待時長等重要資訊。

目前,SDK 生成的 ANR 日誌資訊,基本包含系統生成的 ANR 日誌的所有內容,甚至還包含一些系統日誌中沒有的內容,以及 App增加的自身的業務相關資訊,對分析、定位和解決 ANR 問題,提供了更加強有力的支撐。

3、日誌分析

如開發者接入了SDK,ANR 日誌將自動啟用,出現 ANR 時,會先於系統生成 ANR 日誌。日誌的主要內容介紹如下:

1). ANR 日誌結構

使用日誌分析外掛,我們可以清晰地看到 生成的 ANR 日誌包含的內容以及重點資訊,如下:

圖片2.png

ANR 日誌結構

除了生成的日誌以 Section 分為多個部分,其中,包含重要資訊的 Section 會使用紅色標出,特別重要的資訊還會加粗。另外,每個 Section 有快捷鍵可直接跳轉到相應位置。

2). ANR 概要

概要資訊如下:

圖片3.png

ANR 概要資訊

這部分內容主要從系統獲取,其包含了 ANR 的程序名、ANR 產生的時間、ANR 的原因、ANR 前後幾秒內系統 TOP 程序的 CPU 使用率等。其中,通過 ANR 原因可以得知是輸入事件處理超時,還是 BroadcastReceiver 等其它訊息處理時間過長;通過 CPU 使用率則可以得知是哪個程序佔用 CPU 資源過多。

3). 系統資源使用情況

可記錄在出現 ANR 前一段時間內,CPU 平均使用率、CPU 各核心使用率及其耗時分佈,ANR 程序中 TOP 執行緒的執行耗時及比例、出現頁錯誤的次數,磁碟 IO 操作等待時長及次數等內容。如下:

圖片4.png


系統資源使用情況

當 IO 繁忙導致 ANR 時,io wait time 和 CPU 時間分佈中的 iowait 比例會比較突出;通過 CPU 時間分佈中的 user 和 system 佔比,則可以知道是使用者態程式碼執行耗時過長,還是 Linux 核心的系統呼叫耗時太久。

4). ANR traces

traces 資訊是 ANR 日誌中最關鍵的內容。如U-APM生成的 traces 資訊包含了出現 ANR 時主執行緒的 native 呼叫棧和所有執行緒的 java 呼叫棧。通常死鎖問題通過呼叫棧中的資訊可以很容易發現。






圖片5.png

ANR traces

U-APM SDK 的 traces 由 fork 的子程序生成,不會因 Java 虛擬機器出現 BUG 導致生成 traces 時又出現 native 崩潰,也不會因 dump 時卡死阻塞整個 ANR 日誌的生成。

5). Logcat

以U-APM為例,會在 ANR 時抓取 Android logcat。APM SDK 能繞開部分 ROM 增加的許可權控制,拿到當前 App ANR 前相關的 log 資訊。當前程序以及當前錯誤執行緒輸出的 log 會被重點標出,error 和 warning 也會以顯目的顏色標出。

圖片6.png

logcat

6). 記憶體等其它資訊

通過ANR日誌可以分析出一系列的記憶體資訊,如:

系統的 RAM 總記憶體、剩餘可用記憶體;

當前程序佔用的虛擬記憶體、實體記憶體;

Java 佔用的總記憶體和可用記憶體;

Native 佔用的記憶體和可用記憶體等。

另外,ANR 日誌同 Java 和 Native 崩潰日誌一樣,支援業務自定義日誌內容擴充套件,如:

崩潰前增加簡短的自定義頭資訊;

崩潰前註冊外部檔案,崩潰時其內容將被帶入日誌;

崩潰前快取業務相關的最近若干條操作或資訊;

崩潰時通過回撥返回業務最新內容等。

4、ANR監控工具

選擇一款有超強捕獲能力的專業產品,對於開發者定位和修復穩定性問題至關重要。友盟+U-APM SDK集成了UC 核心團隊強大的技術及友盟+超強的錯誤捕獲能力,通過數萬次捕獲實踐中積累了豐富經驗,在產品、效能和研發能力上都極大保障了開發者定位和修復穩定性問題的超強效率。

作者:友盟全域資料

原文連結

本文為阿里雲原創內容,未經允許不得轉載