閱讀錯誤報告

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

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

Logcat

logcat 記錄是所有 logcat 資訊的字串式傾印。system 部分是保留給架構使用的,其歷史記錄比包含其他所有內容的 main 還要長。每行通常會以 timestamp UID PID TID log-level 開頭,但舊版 Android 可能不會列出 UID

查看事件記錄

這個記錄包含以字串表示的二進位格式記錄訊息。這比 logcat 記錄的雜訊較少,但也較難閱讀。查看事件記錄時,您可以搜尋這個部分的特定程序 ID (PID),瞭解程序的執行情形。基本格式如下:timestamp PID TID log-level log-tag tag-values

記錄層級包括:

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

 

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

ANR 和死結

您可以透過 Bugreport 找出導致應用程式無回應 (ANR) 錯誤和死結事件的原因。

找出無回應的應用程式

如果應用程式未在特定時間內回應 (通常是因為主執行緒遭到封鎖或忙碌),系統會終止程序,並將堆疊轉儲至 /data/anr。如要找出 ANR 背後的罪魁,請在二進位事件記錄檔中使用 grep 搜尋 am_anr

您也可以在 logcat 記錄檔中搜尋 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) 至關重要。錯誤報告包含多個記憶體不足的指標,以及提供記憶體快照的傾印狀態。

找出記憶體不足的問題

記憶體不足可能會導致系統發生抖動,因為系統會終止部分程序來釋放記憶體,但仍會繼續啟動其他程序。如要查看記憶體不足的佐證資料,請檢查二進位事件記錄中 am_proc_diedam_proc_start 項目的濃度。

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

查看歷來指標

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

查看資源耗盡指標

系統耗盡 (分頁、直接回收等) 的其他指標包括 kswapdkworkermmcqd 耗用週期。(請注意,收集的錯誤報告可能會影響 thrashing 指標)。

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

取得記憶體快照

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

廣播

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

查看歷來廣播內容

歷來廣播內容是指已傳送的廣播內容,並以倒敘時間順序列出。

「摘要」部分會概略顯示過去 300 次前景廣播和過去 300 次背景廣播。

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

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

查看有效的廣播

有效廣播是指尚未傳送的廣播。佇列中的數量過多,表示系統無法以足夠的速度調度廣播,無法跟上需求。

查看廣播事件監聽器

如要查看收聽廣播的接收器清單,請查看 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 exit」和「suspend 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

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

找出錯誤報告時間

如要判斷何時擷取錯誤報告,請先檢查 dumpstate: begin 的系統記錄 (Logcat):

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

接著,請檢查核心記錄檔 (dmesg) 的時間戳記,找出 Starting service 'bugreport' 訊息:

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

請從後向前推,找出兩個事件的關聯,並留意「同步時間軸」一節中提到的注意事項。雖然啟動錯誤報告後會發生許多事情,但由於產生錯誤報告的動作會大量載入系統,因此大多數活動都沒什麼用處。

電源

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

錯誤報告中也會包含喚醒鎖定機制的統計資料,這是應用程式開發人員用來指出應用程式需要讓裝置保持開機的機制。(如要進一步瞭解 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 來查看過去三或 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) 和藍牙掃描」。