使用 Logcat 寫入與檢視記錄

Android Studio 的「Logcat」視窗會顯示系統訊息 (如進行垃圾收集) 以及您使用 Log 類別加到應用程式中的訊息。Logcat 會即時顯示訊息,並保留歷史記錄,讓您可以查看過往訊息。

您可以藉由建立篩選條件、修改訊息顯示的資訊量、設定優先等級、只顯示來自應用程式程式碼的訊息,以及搜尋記錄等方式,讓畫面上只顯示您需要的資訊。Logcat 預設只會顯示最近執行的應用程式相關的輸出記錄。

應用程式回傳例外狀況時,Logcat 會顯示訊息,然後顯示相關的堆疊追蹤記錄,裡面有該行程式碼的連結。

「Run」視窗會顯示目前執行中應用程式的記錄訊息。您可以設定 Logcat 的輸出顯示畫面,但是不能設定「Run」視窗。

檢視應用程式記錄

若要顯示應用程式的記錄訊息:

  1. 在裝置上建構並執行應用程式
  2. 按一下「View」>「Tool Windows」>「Logcat」,或按一下工具視窗列中的「Logcat」

Logcat 視窗會顯示透過視窗頂端清單選擇的應用程式記錄訊息,如圖 1 所示。

圖 1. Logcat 視窗。

Logcat 預設只會顯示裝置上執行的應用程式的記錄訊息。若要變更這項預設設定,請參閱如何篩選 logcat 訊息

Logcat 工具列有以下按鈕:

  1. 「Clear logcat」:按一下即可清除看到的記錄。
  2. 「Scroll to the end」:按一下即可跳到記錄末端,查看最新的記錄訊息。如果您點選記錄內的文字行,檢視畫面會暫停捲動留在該處。
  3. 「Up the stack trace」和「Down the stack trace」 :按一下即可上下瀏覽堆疊追蹤,選取列印例外狀況中出現的上一個或下一個檔案名稱。這和您在記錄檔案名稱上按一下的行為相同。
  4. 「Use soft wraps」:按一下即可啟用換行功能,避免水平捲動 (不過如有無法分行的字串,還是需要水平捲動)。
  5. 「Print」:按一下即可列印 Logcat 訊息。在出現的對話方塊中選擇列印偏好設定後,您也可以選擇將訊息儲存為 PDF。
  6. 「Restart」:按一下即可清除記錄並重新啟動 Logcat。與「Clear Logcat」按鈕不同,這樣做會復原並顯示之前的記錄訊息。因此如果 Logcat 停止回應,而您又不希望記錄訊息遺失,就是使用這項功能的最佳時機。
  7. 「Logcat header」:按一下即可開啟「Configure Logcat Header」對話方塊,您可以在此自訂每則 Logcat 訊息的外觀,例如顯示位置、是否顯示日期時間等等。
  8. 「Screen capture」:按一下即可擷取螢幕截圖
  9. 「Screen record」:按一下即可錄製裝置影片最長 3 分鐘。

寫入記錄訊息

Log 類別可讓您建立 Logcat 中顯示的記錄訊息。每一則 Android 記錄訊息都有相關的標記和優先順序。系統記錄訊息的標記是一簡短字串,指出訊息的來源系統元件。

請使用以下記錄方法,按優先順序由高到低依序列出:

任何感覺有用的字串都可以設成使用者定義標記,如目前類別名稱例如,您可以在 Log 方法呼叫中定義標記:

Kotlin

Log.d(tag, message)

Java

Log.d(tag, message);

更完整的選項清單請參閱 Log 類別說明。

除非還在開發,否則絕不要把詳細記錄編譯到應用程式裡。系統會編譯偵錯記錄,但會在執行階段加以移除。系統會一律保留錯誤、警示和資訊等幾種記錄。

關於每個記錄方法,第一個參數都應該是專用的標記,第二個參數則是訊息。系統記錄訊息的標記是一簡短字串,指出訊息的來源系統元件。任何感覺有用的字串都可以設成標記,如目前類別名稱

通常會在類別中宣告 TAG 常數,以便讓第一個參數使用。舉例來說,您可以建立如下所示的資訊記錄訊息:

Kotlin

private const val TAG = "MyActivity"
...
Log.i(TAG, "MyClass.getView() — get item number $position")

Java

private static final String TAG = "MyActivity";
...
Log.i(TAG, "MyClass.getView() — get item number " + position);

注意事項:標記名稱如果超出 23 個字元,則 Logcat 輸出內容顯示時會加以裁剪。

Logcat 訊息格式

記錄訊息格式為:

date time PID-TID/package
priority/tag: message

PID 代表「程序 ID」,「TID」則代表「執行緒 ID」。如果只有一個執行緒,那這兩者也可以是相同內容。

舉例來說,以下記錄訊息的優先順序是 V,並設有 AuthZen 標記:

12-10 13:02:50.071 1901-4229/com.google.android.gms V/AuthZen: Handling delegate intent.

設定記錄層級

您可以設定記錄層級,來控制 Logcat 是否會顯示所有訊息,或者只顯示指出最嚴重條件的訊息。

無論記錄層級設定為何,Logcat 都會持續收集所有訊息。設定只能控制 Logcat 的顯示方式。

在「Log level」選單中,選擇以下任一種內容值:

  • 「Verbose」:顯示所有記錄訊息 (預設值)。
  • 「Debug」:顯示偵錯記錄訊息,以及本清單中低於此層級的訊息,這些訊息只對開發有幫助。
  • 「Info」:顯示一般使用上預期會看到的記錄訊息,以及本清單中低於此層級的訊息。
  • 「Warn」:顯示還不會發生錯誤的可能問題,以及本清單中低於此層級的訊息。
  • 「Error」:顯示會發生錯誤的問題,以及本清單中低於此層級的訊息。
  • 「Assert」:顯示開發人員認為不應該發生的問題。

搜尋 Logcat 訊息

如何搜尋目前在 Logcat 中顯示的訊息:

  1. 如果您想使用規則運算式搜尋模式,也可以點選「Regex」。
  2. 在搜尋欄位 輸入文字串。

    Logcat 輸出內容會按照輸入內容調整。

  3. 按下 Enter 鍵即可在選單中儲存這次工作階段的搜尋字串。
  4. 如果要再度搜尋,請從搜尋選單點選。視需要選取或取消選取「Regex」

篩選 Logcat 訊息

您可以使用篩選條件限制輸出內容,把輸出的記錄限制在方便管理的數量內。

注意事項:篩選條件會套用到所有 Logcat 歷史記錄,不是只有 Logcat 目前顯示的訊息。務必確認其他顯示項目設定正確無誤,才能看到想檢視的篩選輸出內容。

如何定義和套用篩選條件:

  1. 在篩選條件選單中選取篩選條件選項:
    • 「Show only selected application」:只顯示應用程式程式碼產生的訊息 (預設值)。Logcat 會使用作用中應用程式的 PID 篩選記錄訊息。
    • 「No Filters」:不套用任何篩選條件。無論您所選擇的程序為何,Logcat 會顯示所有來自裝置的記錄訊息。
    • 「Edit Filter Configuration」:建立或修改自訂篩選條件。例如,您可以建立篩選條件,藉此同時查看兩個應用程式的記錄訊息。

    定義篩選條件後,您也可以在選單中選擇。如果要移除選單內的項目,請刪除即可。

  2. 如果您選擇「Edit Filter Configuration」,就可以建立或修改篩選條件了:
    1. 在「Create New Logcat Filter」對話方塊中撰寫篩選條件參數︰
      • 「Filter Name」︰輸入您要定義的篩選條件名稱,或在左側窗格中選取現有的篩選條件進行修改。這個名稱只能由小寫字元、底線和數字組成。
      • 「Log Tag」:可選擇指定一個標記。
      • 「Log Message」:可選擇指定記錄訊息文字。
      • 「Package Name」:可選擇指定一個套件名稱。
      • 「PID」:可選擇指定一個程序 ID。
      • 「Log Level」:可選擇一個記錄層級。
      • 「Regex」:選取這個選項後,該參數即可使用規則運算式語法。
    2. 按一下 + 即可在左方窗格新增篩選條件定義。

      如果想移除篩選條件,請從左方窗格點選,然後按一下 -

    3. 完成後,請按一下「OK」

如果您沒有看到所需的記錄訊息,請選取「No Filters」,然後再搜尋特定記錄訊息。

讀取垃圾收集訊息

當發生垃圾收集 (GC) 事件時,資訊會列印至 Logcat。

如要進一步瞭解應用程式記憶體,請用記憶體分析器

Dalvik 記錄訊息

在 Dalvik (不含 ART) 中,每項 GC 都會將下列資訊列印到 Logcat:

D/dalvikvm(PID): GC_Reason Amount_freed,
Heap_stats, External_memory_stats, Pause_time

例子:

D/dalvikvm( 9050): GC_CONCURRENT freed 2049K, 65% free 3571K/9991K, external 4703K/5261K, paused 2ms+2ms

隨著記錄訊息累積起來,您也要注意堆積統計資料的增長。如果這個值持續增加,可能表示發生記憶體流失。

Dalvik 記錄訊息包含下列字詞:

GC 原因
GC 的觸發原因和集合類型。可能顯示的原因包括:
GC_CONCURRENT
堆積開始填滿時,並行的 GC 青出了記憶體。
GC_FOR_MALLOC
由於應用程式嘗試在堆積已經全滿的情況下分配記憶體,導致系統必須停止應用程式並藉由 GC 收回記憶體。
GC_HPROF_DUMP_HEAP
您要求建立 HPROF 檔案分析堆積,此時發生 GC。
GC_EXPLICIT
明確 GC,例如當您呼叫 gc() 時。不過,請避免呼叫此方法;而是信任 GC,以在需要時執行。
GC_EXTERNAL_ALLOC
外部分配記憶體的 GC,例如儲存在本機記憶體的像素資料或 NIO 位元組緩衝區。這只會在 API 級別 10 以下的情況下發生。較新的版本會在 Dalvik 堆積中分配所有資源。
釋出數量
這項 GC 收回的記憶體數量。
堆積統計資料
無堆積和 (活動中物件數量)/(總堆積大小) 的百分比。
外部記憶體統計資料
使用 API 級別 10 以下的外部分配記憶體︰(分配記憶體數量)/(收集發生限制)。
暫停時間
較大的堆積會產生較長的暫停時間。並行暫停時間會顯示兩組暫停:一個位於收集開始時,另一個在即將結束時。

ART 記錄訊息

與 Dalvik 不同的是,ART 不會記錄 GC 未明確要求的訊息。只有在 GC 明確,或者 GC 暫停超過 5 毫秒或 GC 持續時間超過 100 毫秒時,系統才會列印 GC 資訊。如果應用程式不在可以感受到暫停的狀態下 (例如當應用程式在背景執行時,使用者無法察覺發生 GC 暫停),則除了明確 GC 外,這些 GC 都不會輸出任何 GC 資訊。

ART 在垃圾收集記錄訊息中提供下列資訊:

I/art: GC_Reason GC_Name Objects_freed(Size_freed) AllocSpace Objects,
    Large_objects_freed(Large_object_size_freed) Heap_stats LOS objects, Pause_time(s)

例子:

I/art : Explicit concurrent mark sweep GC freed 104710(7MB) AllocSpace objects,
    21(416KB) LOS objects, 33% free, 25MB/38MB, paused 1.230ms total 67.216ms

ART 記錄訊息包含下列字詞:

GC 原因
GC 的觸發原因和集合類型。可能顯示的原因包括:
Concurrent
並未暫停應用程式執行緒的並行 GC。這項 GC 在背景執行緒中執行,不會妨礙分配。
Alloc
由於應用程式嘗試在堆積已經全滿的情況下分配記憶體,系統會啟動 GC。在這種情況下,垃圾收集會在分配執行緒中發生。
Explicit
應用程式明確要求垃圾收集,例如呼叫 System.gc()Runtime.gc()。不過,與 Dalvik 一樣,使用 ART 的最佳做法就是信任 GC,並盡可能避免要求明確 GC。明確 GC 會封鎖分配執行緒,並會用沒必要的方式浪費 CPU 循環,因此不建議使用。明確 GC 也可能會造成其他執行緒先占,而導致資源浪費 (延遲、顫動或停止應用程式)。
NativeAlloc
由於本機分配導致的本機記憶體壓力,如點陣圖或 RenderScript 分配物件。
CollectorTransition
堆積轉換導致的 GC。在執行階段變更 GC 策略便會這樣,例如當應用程式在可感受暫停狀態之間變更時。收集轉換內容會複製自由表空間的所有物件,並貼到觸碰傳輸指標空間,反之亦然。

只有 Android 8.0 以下版本的低 RAM 裝置才會發生此情形,當應用程式的程序狀態從可感受暫停狀態 (如應用程式在前景執行時,此時使用者可以察覺 GC 暫停) 變為無法感受暫停狀態時 (反之亦然) 就會如此。

HomogeneousSpaceCompact
同質空間密集是當自由表空間和自由表空間密集的情況,這通常是在應用程式從無法感受暫停的程序狀態改為其他狀態時會發生的情況。這麼做的主要原因是降低 RAM 使用率,以及整理堆積。
DisableMovingGc
這不是真的 GC 原因,只是說明由於在發生並行堆積密集的時候使用 GetPrimitiveArrayCritical 導致收集遭到封鎖。一般來說,我們非常不建議您使用 GetPrimitiveArrayCritical,它對移動收集工具有所限制。
HeapTrim
這不是真的 GC 原因,只是說明在堆積修剪結束前,系統無法進行 GC。
GC 名稱
ART 有各種可以執行的 GC︰
Concurrent mark sweep (CMS)
收集整個堆積的工具,會釋出所有空間,不含圖像空間。
Concurrent partial mark sweep
收集幾乎整個堆積的工具,會收集除了圖像和 zygote 空間之外的空間。
Concurrent sticky mark sweep
產生的收集工具,只能收集上次 GC 後分配到的自由物件。這項垃圾收集速度較快,暫停時間也較短,所以比完整或部分標註清除還要更常執行。
Marksweep + semispace
非並行的複製 GC,負責堆積轉換和同質空間密集 (以便整理堆積)。
釋出物件
這項 GC 從非大型物件空間中收回的物件數量。
釋出大小
這項 GC 從非大型物件空間中收回的位元組數量。
釋出大型物件
這項垃圾收集從大型物件空間中收回的物件數量。
釋出大型物件大小
這項垃圾收集從大型物件空間中收回的位元組數量。
堆積統計資料
釋出和 (活動中物件數量)/(總堆積大小) 的百分比。
暫停時間
一般來說,暫停時間和執行 GC 時修改的物件參照數量成正比。目前 ART CMS GC 只會暫停一次,在 GC 快結束時發生。移動的 GC 暫停較長,佔了大部分的 GC 時間。

如果您在 Logcat 中看到大量 GC 訊息,也要注意堆積統計資料的增長。如果這個值持續增加,而不會減少,可能表示發生記憶體流失。

另外,如果您看到 GC 指明原因為「Alloc」,表示您即將達到堆積容量上限,應該很快就會發生 OOM 例外狀況。