閱讀錯誤報告

任何類型的開發作業都難免會遇到錯誤,而錯誤報告對於找出及解決問題至關重要。所有 Android 版本都支援使用 Android Debug Bridge (adb) 擷取錯誤報告;Android 4.2 以上版本支援使用「開發人員選項」產生錯誤報告,並透過電子郵件、雲端硬碟等方式分享。

Android 錯誤報告包含 dumpsysdumpstatelogcat 資料,並以文字 (.txt) 格式呈現,方便您輕鬆搜尋特定內容。以下各節將詳細說明錯誤報告元件、常見問題,以及有助於找出與這些錯誤相關聯記錄的實用提示和 grep 指令。大多數章節也包含 grep 指令和輸出內容和/或 dumpsys 輸出內容的範例。

Logcat

logcat記錄會以字串形式傾印所有 logcat資訊。系統部分保留給架構,且比包含所有其他內容的「main」歷史更悠久。每行通常會以 timestamp UID PID TID log-level 開頭,但舊版 Android 可能不會列出 UID

查看事件記錄

這個記錄檔包含以字串形式表示的二進位格式記錄訊息。這比 logcat 記錄更簡潔,但閱讀起來也比較困難。查看事件記錄時,您可以在這個部分搜尋特定程序 ID (PID),瞭解程序執行的動作。基本格式為: timestamp PID TID log-level log-tag tag-values

記錄層級包括:

  • V:詳細資訊
  • D:debug
  • I:資訊
  • W:警告
  • E:錯誤

 

如需其他實用的事件記錄標記,請參閱 /services/core/java/com/android/server/EventLogTags.logtags

ANR 和死結

錯誤報告可協助您找出導致應用程式無回應 (ANR) 錯誤和死結事件的原因。

找出沒有回應的應用程式

如果應用程式在特定時間內沒有回應 (通常是因為主執行緒遭到封鎖或忙碌),系統就會終止程序並將堆疊傾印至 /data/anr。如要找出導致 ANR 的原因,請在二進位事件記錄中搜尋 am_anr

您也可以在 logcat 記錄中 grep ANR in,其中包含 ANR 發生時使用 CPU 的相關資訊。

尋找堆疊追蹤

您通常可以找到與 ANR 相對應的堆疊追蹤。請確認 VM 追蹤記錄中的時間戳記和 PID 與您要調查的 ANR 相符,然後檢查程序的執行緒。注意事項:

  • 主執行緒只會顯示執行緒在發生 ANR 時執行的作業,這可能與 ANR 的真正原因相符,也可能不符。(錯誤報告中的堆疊可能無關,可能是其他項目卡住一段時間,但時間不夠長,因此不會發生 ANR,之後才解除卡住狀態)。
  • 可能有多個堆疊追蹤記錄集 (VM TRACES JUST NOWVM TRACES AT LAST ANR)。請確認您查看的是正確的專案。

找出死結

死結通常會先以 ANR 的形式出現,因為執行緒會卡住。如果死結影響系統伺服器,監控程式最終會終止伺服器,導致記錄檔中出現類似以下內容的項目:WATCHDOG KILLING SYSTEM PROCESS。從使用者的角度來看,裝置會重新啟動,但從技術上來說,這屬於執行階段重新啟動,而非真正的重新啟動。

  • 執行階段重新啟動時,系統伺服器會終止並重新啟動,使用者會看到裝置返回啟動動畫。
  • 重新啟動:核心當機,使用者會看到裝置返回 Google 開機標誌。

如要找出死結,請檢查 VM 追蹤記錄區段,找出執行緒 A 等待執行緒 B 持有的項目,而執行緒 B 又等待執行緒 A 持有的項目。

活動

活動是應用程式元件,可提供使用者互動的畫面,讓他們撥號、拍照、傳送電子郵件等。從錯誤報告的角度來看,「活動」是使用者可執行的單一專注事項,因此找出當機時處於焦點的活動非常重要。活動 (透過 ActivityManager) 會執行程序,因此找出特定活動的所有程序停止和啟動作業,也有助於進行疑難排解。

查看重點活動

如要查看專注活動記錄,請搜尋 am_focused_activity

查看程序開始

如要查看程序啟動記錄,請搜尋 Start proc

判斷裝置是否正在猛烈運作

如要判斷裝置是否猛烈運作,請檢查 am_proc_diedam_proc_start 周圍的活動是否在短時間內異常增加。

記憶體

由於 Android 裝置的實體記憶體通常有限,因此管理隨機存取記憶體 (RAM) 至關重要。錯誤報告包含多項記憶體不足的指標,以及提供記憶體快照的 dumpstate。

找出記憶體不足的情況

記憶體不足可能會導致系統頻繁終止部分程序來釋放記憶體,但又持續啟動其他程序,如要查看記憶體不足的佐證,請檢查二進位事件記錄檔中 am_proc_diedam_proc_start 項目是否集中出現。

記憶體不足也可能導致工作切換速度變慢,並阻礙返回嘗試 (因為使用者嘗試返回的工作已終止)。如果啟動器遭到終止,使用者觸控主畫面按鈕時,啟動器就會重新啟動,記錄檔也會顯示啟動器重新載入內容。

查看歷來指標

二進位事件記錄中的 am_low_memory 項目表示最後一個快取程序已終止。完成後,系統會開始終止服務。

查看資源耗盡指標

系統顛簸 (分頁、直接回收等) 的其他指標包括 kswapdkworkermmcqd 消耗週期。(請注意,收集錯誤報告可能會影響磁碟空間不足指標)。

ANR 記錄檔可提供類似的記憶體快照。

取得記憶體快照

記憶體快照是列出執行中 Java 和原生程序的傾印狀態 (詳情請參閱「查看整體記憶體配置」)。請注意,快照只會提供特定時間點的狀態;系統在快照建立前可能處於較好 (或較差) 的狀態。

廣播

應用程式會產生廣播,在目前應用程式內或傳送至其他應用程式。廣播接收器會訂閱特定訊息 (透過篩選器),以便監聽及回應廣播。錯誤報告包含已傳送和未傳送的廣播資訊,以及監聽特定廣播的所有接收器 dumpsys。

查看歷來廣播

歷來訊息是指已傳送的訊息,會依時間倒序排列。

「摘要」部分會顯示最近 300 次前景和背景廣播的總覽。

「詳細資料」部分包含最近 50 次前景和背景廣播的完整資訊,以及每次廣播的接收器。接收器必須具備下列條件:

  • BroadcastFilter 項目會在執行階段註冊,且只會傳送至已執行的程序。
  • ResolveInfo 項目是透過資訊清單項目註冊。如果每個 ResolveInfo 的程序尚未執行,ActivityManager 就會啟動程序。

查看進行中的直播

有效廣播是指尚未傳送的廣播。如果佇列中的數字很大,表示系統無法快速傳送廣播,導致廣播延遲。

查看廣播事件監聽器

如要查看正在監聽廣播的接收器清單,請檢查 dumpsys activity broadcasts 中的接收器解析器表格。以下範例會顯示所有監聽 USER_PRESENT 的接收器。

監控系統衝突

監控爭用記錄有時會指出實際的監控爭用,但通常表示系統負載過重,導致所有作業都變慢。您可能會在系統或事件記錄中,看到 ART 記錄的長時間監控事件。

系統記錄檔:

10-01 18:12:44.343 29761 29914 W art     : Long monitor contention event with owner method=void android.database.sqlite.SQLiteClosable.acquireReference() from SQLiteClosable.java:52 waiters=0 for 3.914s

在事件記錄中:

10-01 18:12:44.364 29761 29914 I dvm_lock_sample: [com.google.android.youtube,0,pool-3-thread-9,3914,ScheduledTaskMaster.java,138,SQLiteClosable.java,52,100]

背景編譯

編譯作業可能很耗費資源,並造成裝置負擔。

下載 Google Play 商店更新時,編譯作業可能會在背景執行。在這種情況下,Google Play 商店應用程式 (finsky) 和 installd 的訊息會顯示在 dex2oat 訊息之前。

如果應用程式載入尚未編譯的 DEX 檔案,編譯作業也可能在背景執行。在這種情況下,您不會看到 finskyinstalld 記錄。

敘事

如要建立問題的敘事脈絡 (問題的起因、發生經過、系統的反應),必須有完整的事件時間軸。您可以利用錯誤報告中的資訊,同步處理多個記錄檔的時間軸,並判斷錯誤報告的確切時間戳記。

同步時間軸

錯誤報告會反映多個平行時間軸:系統記錄、事件記錄、核心記錄,以及廣播、電池統計資料等多個專用時間軸。遺憾的是,時間軸通常會使用不同的時間基準回報。

系統和事件記錄時間戳記與使用者位於同一時區 (大多數其他時間戳記也是如此)。舉例來說,當使用者輕觸主畫面按鈕時,系統記錄會回報:

10-03 17:19:52.939  1963  2071 I ActivityManager: START u0 {act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x10200000 cmp=com.google.android.googlequicksearchbox/com.google.android.launcher.GEL (has extras)} from uid 1000 on display 0

針對相同動作,事件記錄會回報:

10-03 17:19:54.279  1963  2071 I am_focused_activity: [0,com.google.android.googlequicksearchbox/com.google.android.launcher.GEL]

核心 (dmesg) 記錄使用不同的時間基準,並以開機載入程式完成後經過的秒數標記記錄項目。如要將這個時間刻度註冊到其他時間刻度,請搜尋 suspend exitsuspend entry 訊息:

<6>[201640.779997] PM: suspend exit 2015-10-03 19:11:06.646094058 UTC
…
<6>[201644.854315] PM: suspend entry 2015-10-03 19:11:10.720416452 UTC

由於核心記錄可能不會在暫停期間包含時間,因此您應在暫停進入和退出訊息之間,逐步註冊記錄。此外,核心記錄使用世界標準時間時區,因此必須調整為使用者時區。

找出錯誤報告時間

如要判斷回報錯誤的時間,請先檢查系統記錄 (Logcat) 中的 dumpstate: begin

10-03 17:19:54.322 19398 19398 I dumpstate: begin

接著,檢查 Starting service 'bugreport' 訊息的 Kernel 記錄 (dmesg) 時間戳記:

<5>[207064.285315] init: Starting service 'bugreport'...

請回溯時間,找出這兩個事件的關聯性,並留意「同步時間軸」一節中提到的注意事項。雖然啟動錯誤報告後會發生許多事,但由於擷取錯誤報告會大幅增加系統負載,因此大部分活動並非很有用。

電源

事件記錄包含螢幕電源狀態,其中 0 代表螢幕關閉、1 代表螢幕開啟,2 則代表 Keyguard 完成。

錯誤報告也包含喚醒鎖定的統計資料。應用程式開發人員會使用喚醒鎖定機制,指出應用程式需要讓裝置保持開啟狀態。(如要進一步瞭解 Wake Lock,請參閱「PowerManager.WakeLock」 和「讓 CPU 保持運作」。)

匯總的 Wake Lock 持續時間統計資料只會追蹤 Wake Lock 實際負責讓裝置保持喚醒狀態的時間,不會納入螢幕開啟的時間。此外,如果同時持有多個 Wake Lock,系統會將 Wake Lock 持有時間分配給這些 Wake Lock。

如要進一步瞭解電源狀態,請使用 Battery Historian。這項 Google 開放原始碼工具可使用 Android 錯誤報告檔案分析耗電量。

套件

DUMP OF SERVICE package」部分會顯示應用程式版本 (和其他實用資訊)。

程序

錯誤報告包含大量程序資料,包括開始和停止時間、執行時間長度、相關聯的服務、oom_adj分數等。如要進一步瞭解 Android 管理程序的方式,請參閱「程序和執行緒」。

判斷程序執行階段

procstats」部分包含程序和相關服務的完整統計資料,包括執行時間長度。如要查看簡短易懂的摘要,請搜尋 AGGREGATED OVER,查看過去 3 或 24 小時的資料,然後搜尋 Summary:,查看程序清單、這些程序以各種優先順序執行的時間長度,以及以 min-average-max PSS/min-average-max USS 格式表示的 RAM 使用量。

程序執行原因

dumpsys activity processes」部分會列出目前執行的所有程序,並依 oom_adj 分數排序 (Android 會為程序指派 oom_adj 值,藉此指出程序的重要性,而 ActivityManager 可以動態更新該值)。輸出內容與記憶體快照類似,但包含導致程序執行的額外資訊。在下方範例中,粗體項目表示 gms.persistent 程序以 vis (可見) 優先順序執行,因為系統程序會繫結至 NetworkLocationService

掃描

請按照下列步驟找出執行過多藍牙低功耗 (BLE) 掃描的應用程式:

  • 找出 BluetoothLeScanner 的記錄訊息:
    $ grep 'BluetoothLeScanner' ~/downloads/bugreport.txt
    07-28 15:55:19.090 24840 24851 D BluetoothLeScanner: onClientRegistered() - status=0 clientIf=5
    
  • 在記錄訊息中找出 PID。在本例中,「24840」和「24851」分別是 PID (程序 ID) 和 TID (執行緒 ID)。
  • 找出與 PID 相關聯的應用程式:
    PID #24840: ProcessRecord{4fe996a 24840:com.badapp/u0a105}
    

    在本範例中,套件名稱為 com.badapp

  • 在 Google Play 查詢套件名稱,找出負責的應用程式: https://play.google.com/store/apps/details?id=com.badapp

注意:如果裝置搭載 Android 7.0,系統會收集 BLE 掃描的資料,並將這些活動與啟動應用程式建立關聯。詳情請參閱「藍牙低功耗 (LE) 和藍牙掃描」。