天天看點

一文教你輕松搞定ANR異常捕獲與分析方法1. ANR 産生原理2. ANR 日志生成原理3、日志分析4、ANR監控工具

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 的流程。

一文教你輕松搞定ANR異常捕獲與分析方法1. ANR 産生原理2. ANR 日志生成原理3、日志分析4、ANR監控工具

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 日志包含的内容以及重點資訊,如下:

一文教你輕松搞定ANR異常捕獲與分析方法1. ANR 産生原理2. ANR 日志生成原理3、日志分析4、ANR監控工具

ANR 日志結構

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

2). ANR 概要

概要資訊如下:

一文教你輕松搞定ANR異常捕獲與分析方法1. ANR 産生原理2. ANR 日志生成原理3、日志分析4、ANR監控工具

ANR 概要資訊

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

3). 系統資源使用情況

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

一文教你輕松搞定ANR異常捕獲與分析方法1. ANR 産生原理2. ANR 日志生成原理3、日志分析4、ANR監控工具

系統資源使用情況

當 IO 繁忙導緻 ANR 時,io wait time 和 CPU 時間分布中的 iowait 比例會比較突出;通過 CPU 時間分布中的 user 和 system 占比,則可以知道是使用者态代碼執行耗時過長,還是 Linux 核心的系統調用耗時太久。

4). ANR traces

traces 資訊是 ANR 日志中最關鍵的内容。如U-APM生成的 traces 資訊包含了出現 ANR 時主線程的 native 調用棧和所有線程的 java 調用棧。通常死鎖問題通過調用棧中的資訊可以很容易發現。

一文教你輕松搞定ANR異常捕獲與分析方法1. ANR 産生原理2. ANR 日志生成原理3、日志分析4、ANR監控工具

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 也會以顯目的顔色标出。

一文教你輕松搞定ANR異常捕獲與分析方法1. ANR 産生原理2. ANR 日志生成原理3、日志分析4、ANR監控工具

logcat

6). 記憶體等其它資訊

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

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

目前程序占用的虛拟記憶體、實體記憶體;

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

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

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

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

崩潰前注冊外部檔案,崩潰時其内容将被帶入日志;

崩潰前緩存業務相關的最近若幹條操作或資訊;

崩潰時通過回調傳回業務最新内容等。

4、ANR監控工具

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