為應用程式偵錯

Android Studio 提供偵錯工具,可讓您執行以下及其他操作:

  • 選取要在哪個裝置上對應用程式進行偵錯。
  • 設定 Java、Kotlin 和 C/C++ 程式碼中的中斷點。
  • 在執行階段檢查變數及評估運算式。

本頁提供基本偵錯工具作業的操作說明。如需其他說明文件,另請參閱 IntelliJ IDEA 偵錯文件

啟用偵錯功能

開始偵錯前,請先備妥以下項目:

  • 啟用裝置偵錯功能:

    如果您使用的是模擬器,系統預設會啟用這項功能。但如果是已連結的裝置,您必須在裝置開發人員選項中啟用偵錯功能

  • 執行可進行偵錯的建構變數:

    您必須使用建構設定中包含 debuggable true建構變數。通常,您只需選取每個 Android Studio 專案包含的預設「debug」變數 (即使未顯示在 build.gradle 檔案中)。但如果您定義了可進行偵錯的新建構類型,則必須在建構類型中加入 「debuggable true」:

    Groovy

    android {
        buildTypes {
            customDebugType {
                debuggable true
                ...
            }
        }
    }
    

    Kotlin

    android {
        buildTypes {
            create("customDebugType") {
                debuggable = true
                ...
            }
        }
    }
    

    這個屬性也適用於含有 C/C++ 程式碼的模組 (系統不再使用 jniDebuggable 屬性)。

    如果您的應用程式依附於程式庫模組,而您也想對該模組進行偵錯,則必須將程式庫與 debuggable true 一併附在套件中,讓程式庫保留偵錯符號。如要確保應用程式專案的可偵錯變數接收程式庫模組的可偵錯變數,請務必發布非預設的程式庫版本

開始偵錯

您可以按照以下方式開始偵錯工作階段:

  1. 在應用程式的程式碼中設定一些中斷點
  2. 在工具列中的目標裝置下拉式選單中,選取要在哪個裝置上對應用程式進行偵錯。

    目標裝置下拉式選單。

    如果您尚未設定任何裝置,則必須透過 USB 連結裝置建立 AVD,才能使用 Android Emulator

  3. 按一下工具列中的「Debug」圖示

    如果看到對話方塊,詢問您是否想要「switch from Run to Debug」,代表應用程式已在裝置上執行,並且會重新啟動以開始偵錯。如果想讓相同的應用程式執行個體保持運作,請按一下「Cancel Debug」,然後將偵錯工具附加至執行中的應用程式

    否則,Android Studio 會建構 APK 並使用偵錯金鑰進行簽署,然後在所選裝置上安裝,接著執行 APK。如果您將 C 和 C++ 程式碼新增至專案,Android Studio 也會在「Debug」視窗中執行 LLDB 偵錯工具,以對您的原生程式碼進行偵錯。

  4. 如果「Debug」視窗未開啟,請依序選取「View」>「Tool Windows」>「Debug」,或按一下工具視窗列中的「Debug」圖示 ),然後按一下 「Debugger」分頁標籤,如圖 1 所示。

    圖 1. 「Debugger」視窗會顯示變數目前的執行緒和物件樹狀結構

將偵錯工具附加至執行中的應用程式

如果應用程式已在裝置上執行,您不必重新啟動應用程式,就可以開始偵錯;方法如下:

  1. 按一下「Attach debugger to Android process」圖示
  2. 在「Choose Process」對話方塊中,選取要附加偵錯工具的程序。

    如果您使用的是模擬器或已解鎖裝置,您可以勾選「Show all processes」來查看所有程序。

    從「Use Android Debugger Settings from」下拉式選單中,選取現有的執行/偵錯設定 (對於 C 和 C++ 程式碼,這麼做可讓您在現有設定中重複使用 LLDB 啟動指令、LLDB 附加後指令和符號目錄)。如果您目前沒有執行/偵錯設定,請選取「Create New」。這個選項會啟用「Debug Type」下拉式選單,您可以在這裡選取不同的偵錯類型。根據預設,Android Studio 會使用「Auto」偵錯類型,根據專案是包含 Java 或 C/C++ 程式碼,為您選擇最適合的偵錯工具選項。

  3. 按一下「OK」

    系統會隨即顯示「Debug」視窗。

注意:Android Studio 偵錯工具和垃圾收集器已大致整合。Android 虛擬機器會保證系統不會將偵錯工具發現的任何物件收集為垃圾,直到偵錯工具中斷連線為止。在偵錯工具連線的情況下,這可能會導致系統在一段時間後積聚物件。舉例來說,如果偵錯工具看到執行中的執行緒,則直到偵錯工具中斷連線前,系統都不會將相關的 Thread 物件收集為垃圾 (即使執行緒已終止)。

變更偵錯工具類型

由於必須使用不同偵錯工具對 Java/Kotlin 程式碼和 C/C++ 程式碼進行偵錯,因此 Android Studio 偵錯工具可讓您選取要使用的偵錯工具類型。根據預設,Android Studio 會使用「Auto」偵錯工具類型,根據在您專案中偵測到的語言,決定要使用的偵錯工具。不過,您可以在偵錯設定中手動選取偵錯工具 (按一下「Run」>「Edit Configurations」),或點選「Run」>「Attach debugger to Android process」,然後在畫面上顯示的對話方塊中選取。

可用的偵錯類型如下:

Auto
如果想讓 Android Studio 自動針對要偵錯的程式碼選擇最佳選項,請選取這個偵錯類型。舉例來說,如果您的專案有任何 C 或 C++ 程式碼,Android Studio 會自動使用「Dual」偵錯類型。否則,Android Studio 會使用「Java」偵錯類型。
Java
如果只想針對以 Java 或 Kotlin 編寫的程式碼進行偵錯,請選取這個偵錯類型;Java 偵錯工具會忽略您在原生程式碼中設定的任何中斷點或觀察點。
Native (僅適用於 C/C++ 程式碼)
如果您只想使用 LLDB 對程式碼進行偵錯,請選取這個偵錯類型。採用該偵錯類型時,無法查看 Java 偵錯工具的工作階段檢視畫面。根據預設,LLDB 只會檢查原生程式碼,並忽略 Java 程式碼中的中斷點。如要一併對 Java 程式碼進行偵錯,請改用「Auto」或「Dual」偵錯類型。

原生偵錯功能僅適用於符合下列條件的裝置:

  • 裝置支援 run-as

    如要確認裝置是否支援 run-as,請在已連線至裝置的 ADB 殼層中執行下列指令:

    run-as your-package-name pwd
    

    your-package-name 替換成應用程式的套件名稱。如果裝置支援 run-as,則指令傳回時不應出現任何錯誤。

  • 裝置已啟用 ptrace

    如要檢查 ptrace 是否已啟用,請在已連線至裝置的 ADB 殼層中執行下列指令:

    sysctl kernel.yama.ptrace_scope
    

    如果已啟用 ptrace,這個指令會輸出值 0unknown key 錯誤。如果未啟用 ptrace,則會輸出 0 以外的值。

Dual (僅適用於 C/C++ 程式碼)
如果偵錯時要在 Java 和原生程式碼之間切換,請選取這個偵錯類型。Android Studio 會同時將 Java 偵錯工具和 LLDB 附加至應用程式程序 (一項程序用於 Java 偵錯工具,另一項用於 LLDB),方便您檢查 Java 和原生程式碼中的中斷點,而不必重新啟動應用程式或變更偵錯設定。

在圖 2 中,請注意「Debug」視窗名稱右側的兩個分頁。 由於應用程式同時含有 Java 和 C++ 程式碼,其中一個分頁用於原生程式碼偵錯,另一個分頁則用於 Java 程式碼偵錯,如「-java」所示。

圖 2. 用於原生程式碼偵錯的分頁,以及 Java 程式碼偵錯的分頁

注意事項:如要對經過編譯器最佳化調整的原生程式碼進行偵錯,您可能會收到以下警告訊息:This function was compiled with optimizations enabled. Some debugger features may not be available。使用最佳化標記 (例如 -O 標記) 時,編譯器會變更編譯的程式碼,藉此提高執行效率。偵錯工具可能因此難以將最佳化的編譯程式碼對應至原本的原始碼,而導致回報非預期或不正確的資訊。基於這項原因,建議您在對原生程式碼進行偵錯時停用編譯器最佳化功能。

使用系統記錄

系統記錄會在應用程式偵錯時顯示系統訊息。這些訊息包括裝置上執行的應用程式資訊。如要使用系統記錄對應用程式進行偵錯,請確認程式碼在應用程式開發階段會寫入記錄訊息,並輸出例外狀況堆疊追蹤。

編寫程式碼中的記錄訊息

如要在程式碼中編寫記錄訊息,請使用 Log 類別。記錄訊息可在您與應用程式互動時收集系統偵錯輸出內容,協助您瞭解執行流程;還能指出應用程式出錯的部分。如要進一步瞭解記錄功能,請參閱「寫入及查看記錄」。

以下範例說明如何新增記錄訊息,以判斷活動開始時,先前的狀態資訊是否可供使用:

Kotlin

import android.util.Log
...
private val TAG: String = MyActivity::class.java.simpleName
...
class MyActivity : Activity() {
    ...
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        if (savedInstanceState != null) {
            Log.d(TAG, "onCreate() Restoring previous state")
            /* restore state */
        } else {
            Log.d(TAG, "onCreate() No saved state available")
            /* initialize app */
        }
    }
}

Java

import android.util.Log;
...
public class MyActivity extends Activity {
    private static final String TAG = MyActivity.class.getSimpleName();
    ...
    @Override
    public void onCreate(Bundle savedInstanceState) {
       ...
       if (savedInstanceState != null) {
            Log.d(TAG, "onCreate() Restoring previous state");
            /* restore state */
        } else {
            Log.d(TAG, "onCreate() No saved state available");
            /* initialize app */
        }
    }
}

在開發期間,您的程式碼也可以擷取例外狀況,並將堆疊追蹤寫入系統記錄:

Kotlin

fun someOtherMethod() {
    try {
        ...
    } catch (e : SomeException) {
        Log.d(TAG, "someOtherMethod()", e)
    }
}

Java

void someOtherMethod() {
    try {
        ...
    } catch (SomeException e) {
        Log.d(TAG, "someOtherMethod()", e);
    }
}

注意:準備好發布應用程式時,請從程式碼中移除偵錯記錄訊息和堆疊追蹤輸出呼叫。做法是設定 DEBUG 標記,並將偵錯記錄訊息放入條件陳述式中。

查看系統記錄

您可以在「Logcat」視窗中查看及篩選偵錯和其他系統訊息。舉例來說,您可以在垃圾收集發生時查看訊息,或是使用 Log 類別新增至應用程式的訊息。

如要使用 logcat,請開始偵錯,並選取底部工具列中的「Logcat」分頁標籤,如圖 3 所示。

圖 3. 包含篩選器設定的「Logcat」視窗

如需 logcat 和篩選選項的說明,請參閱「使用 Logcat 寫入及查看記錄」。

使用中斷點

Android Studio 支援數種會觸發不同偵錯動作的中斷點。最常見的類型是行中斷點,用於在指定的程式碼行暫停執行應用程式。暫停期間,您可以檢查變數、評估運算式,然後逐行執行,以判斷執行階段錯誤的原因。

如要新增行中斷點,請按照下列步驟操作:

  1. 找出您要暫停執行作業的程式碼行,然後按一下該行程式碼左側的溝槽,或是將插入點放到該行,再按下 Control + F8 鍵 (在 Mac 上則是 Command + F8 鍵)。
  2. 如果應用程式已經在執行中,您不必更新應用程式就能新增中斷點,只要按一下「Attach debugger to Android proccess」圖示 即可。否則,請按一下「Debug」圖示 開始偵錯。

圖 3. 當您設定中斷點,程式碼行旁邊會顯示紅點

當程式碼執行到中斷點時,Android Studio 就會暫停執行您的應用程式。然後,您就可以使用「Debugger」分頁中的工具確認應用程式的狀態:

  • 如要檢查變數的物件樹狀結構,請在「Variables」檢視畫面中展開該結構。如果找不到「Variables」檢視畫面,請按一下「Restore Variables View」圖示

  • 如要評估目前執行階段的運算式,請按一下「Evaluate Expression」圖示

  • 如要前往下一行程式碼 (不進入方法),請按一下「Step Over」圖示

  • 如要前往方法呼叫中的第一行,請按一下「Step Into」圖示

  • 如要前往目前方法外的下一行,請按一下「Step Out」圖示

  • 如要繼續照常執行應用程式,請按一下「Resume Program」圖示

如果專案使用任何原生程式碼,根據預設,「Auto」偵錯類型會同時將 Java 偵錯工具和 LLDB 附加至應用程式,以兩個不同程序執行;因此檢查中斷點時就能在 Java 和 C/C++ 間切換,而不必重新啟動應用程式或變更設定。

注意:如要讓 Android Studio 偵測 C 或 C++ 程式碼中的中斷點,您必須使用支援 LLDB 的偵錯類型,例如 Auto、Native 或 Dual 等。如要變更 Android Studio 使用的偵錯類型,請編輯偵錯設定。如要進一步瞭解不同的偵錯類型,請參閱使用其他偵錯類型的相關章節。

當 Android Studio 將您的應用程式部署至目標裝置時,「Debug」視窗會隨即開啟,其中針對每個偵錯工具程序開啟分頁或偵錯工作階段檢視畫面,如圖 4 所示。

圖 4. 使用 LLDB 對原生程式碼進行偵錯

  1. 當 LLDB 偵錯工具遇到 C/C++ 程式碼中的中斷點,Android Studio 就會切換至「<your-module>分頁。「Frames」、「Variables」和「Watches」窗格也可供使用,而且運作方式與 Java 程式碼偵錯相同。雖然 LLDB 工作階段檢視畫面中並未提供「Threads」窗格,但您可以使用「Frames」窗格中的下拉式清單存取應用程式程序。如要進一步瞭解這些窗格,請參閱關於如何偵錯視窗框架檢查變數的章節。

    注意:檢查原生程式碼中的中斷點時,Android 系統會將執行應用程式 Java 位元碼的虛擬機器暫停。這表示檢查原生程式碼中的中斷點時,您將無法與 Java 偵錯工具互動,也無法從 Java 偵錯工具工作階段擷取任何狀態資訊。

  2. 當 Java 偵錯工具遇到 Java 程式碼中的中斷點時,Android Studio 就會切換至「<your-module>-java」分頁。
  3. 使用 LLDB 偵錯時,您可以使用 LLDB 工作階段檢視畫面中的 LLDB 終端機,將指令列選項傳遞給 LLDB。如果您希望 LLDB 在每次應用程式偵錯開始時執行特定指令 (無論是在偵錯工具附加至應用程式程序之前或之後立即執行),則可以將這些指令新增至偵錯設定

對 C/C++ 程式碼進行偵錯時,您也可以設定特殊的中斷點類型 (稱為「觀察點」),如此一來,當應用程式與特定記憶體區塊互動時,應用程式程序就會暫停。詳情請參閱關於如何新增觀察點的章節。

查看及設定中斷點

如要查看所有中斷點並調整中斷點設定,請按一下「Debug」視窗左側的「View Breakpoints」圖示 。「Breakpoints」視窗會隨即顯示,如圖 5 所示。

圖 5. 「Breakpoints」視窗會列出目前所有的中斷點,且包含各中斷點的行為設定

「Breakpoints」視窗可讓您從左側清單中啟用或停用各個中斷點。如果已停用中斷點,Android Studio 就不會在執行到中斷點時暫停應用程式。從清單中選取中斷點即可調整設定。您可以先將中斷點設為停用,然後讓系統在執行到其他中斷點後再啟用。您也可以設定執行到中斷點後是否應停用該中斷點。如要為任何例外狀況設定中斷點,請在中斷點清單中選取「Exception Breakpoints」

偵錯視窗框架

在「Debugger」視窗中,「Frames」窗格可讓您檢查導致執行到目前中斷點的堆疊框架。您可以藉此瀏覽及檢查堆疊框架,並檢查 Android 應用程式中的執行緒清單。如要選取執行緒,請使用執行緒選取器下拉式選單,並查看該執行緒的堆疊框架。按一下框架中的元素,即可在編輯器中開啟來源。您也可以自訂執行緒顯示方式,並按照視窗框架指南中的說明匯出堆疊框架。

檢查變數

在「Debugger」視窗中,「Variables」窗格可讓您在系統於中斷點停止應用程式時檢查變數,然後從「Frames」窗格選取框架。「Variables」窗格還可讓您使用靜態方法和/或所選框架內提供的變數來評估特設運算式。

「Watches」窗格提供類似的功能,但新增至「Watches」窗格的運算式會在偵錯工作階段之間保持不變。針對經常存取的變數和欄位,或是能為目前偵錯工作階段提供實用狀態的變數和欄位,建議您新增觀察點。「Variables」和「Watches」窗格如圖 5 所示。

如要將變數或運算式新增至「Watches」清單,請按照下列步驟操作:

  1. 開始偵錯。
  2. 在「Watches」窗格中,按一下「Add」圖示
  3. 在隨即顯示的文字方塊中,輸入您要監看的變數或運算式名稱,然後按下 Enter 鍵。

如要將項目從「Watches」清單中移除,請選取該項目,然後按一下「Remove」圖示

如要重新排列「Watches」清單中的元素,請選取項目並按一下「Up」圖示 或「Down」圖示

圖 6. 「Debugger」視窗中的「Variables」和「Watches」窗格

新增觀察點

對 C/C++ 程式碼進行偵錯時,您可以設定特殊的中斷點類型 (稱為「觀察點」),如此一來,當應用程式與特定記憶體區塊互動時,應用程式程序就會暫停。舉例來說,假設您將兩個指標設為指向某個記憶體區塊,並針對該區塊指派觀察點,則使用任一指標存取該記憶體區塊均會觸發觀察點。

在 Android Studio 中,您只要選取特定變數,就能在執行階段建立觀察點,但 LLDB 只會將觀察點指派至系統分配給該變數的記憶體區塊,而非變數本身。這與在「Watches」窗格中新增變數的做法不同;「Watches」可讓您監控變數的值,但系統在記憶體中讀取或變更值時,您無法暫停應用程式程序。

注意:當應用程式程序結束函式時,系統會將該函式的區域變數從記憶體解除分配,因此您必須重新指派為這些變數建立的任何觀察點。

您必須符合下列條件,才能設定觀察點:

  • 目標實體裝置或模擬器使用 x86 或 x86_64 CPU。如果您的裝置使用 ARM CPU,則必須將記憶體中變數位址的界線對齊至適合 32 位元處理器的 4 個位元組,或 64 位元處理器的 8 個位元組。您可以在變數宣告中指定 __attribute__((aligned(num_bytes))),讓原生程式碼中的變數對齊,如下所示:
    // For a 64-bit ARM processor
    int my_counter __attribute__((aligned(8)));
    
  • 您已指派三個或更少觀察點。Android Studio 在 x86 或 x86_64 目標裝置上最多只能支援四個觀察點。其他裝置可能支援較少觀察點。

注意:使用 32 位元 ARM ABI 對應用程式進行偵錯時,如果新增觀察點或將滑鼠遊標懸停在程式碼內的變數上來調查數值,可能會造成當機情形。請改用 64 位元的 ARM、x86 或 x86_64 二進位檔進行偵錯。我們將在日後的 Android Studio 版本中修正這個問題。

如果您符合上述條件,可以按照下列步驟新增觀察點:

  1. 應用程式在中斷點暫停時,請前往 LLDB 工作階段檢視畫面中的「Variables」窗格
  2. 在位於要追蹤記憶體區塊的變數上按一下滑鼠右鍵,然後選取「Add Watchpoint」。畫面隨即會顯示設定觀察點的對話方塊,如圖 7 所示。

    圖 7. 將觀察點新增至記憶體中的變數

  3. 透過下列選項設定觀察點:
    • 「Enabled」:如果想讓 Android Studio 暫時忽略觀察點,可以取消選取這個選項。Android Studio 仍會儲存觀察點,方便您日後在偵錯工作階段中存取。
    • 「Suspend」:根據預設,Android 系統存取已指派給觀察點的記憶體區塊時,會暫停您的應用程式程序。 如果您不想要這項行為,可以取消選取這個選項;這麼做會顯示其他選項,可用於自訂系統與觀察點互動時的行為:「Log message to console」和「Remove [觀察點] when hit」
    • 「Access Type」:選取應用程式在嘗試「Read」或「Write」系統分配給該變數的記憶體區塊時,是否觸發觀察點。如要在讀取或寫入時觸發觀察點,請選取「Any」
  4. 按一下「Done」。

如要查看所有觀察點並調整觀察點設定,請按一下「Debug」視窗左側的「View Breakpoints」圖示 。「Breakpoints」對話方塊會隨即顯示,如圖 8 所示。

圖 8. 「Breakpoints」對話方塊會列出目前的觀察點,且包含各觀察點的行為設定

新增觀察點後,按一下「Debug」視窗左側的「Resume Program」圖示 ,繼續執行應用程式程序。根據預設,如果應用程式嘗試存取設有觀察點的記憶體區塊,Android 系統會暫停應用程式程序,接著應用程式最近一次執行的程式碼行旁邊會顯示觀察點圖示 ,如圖 9 所示。

圖 9. Android Studio 會指出觸發觀察點前,應用程式正在執行的程式碼行

查看及變更資源值顯示格式

在偵錯模式中,您可以查看資源值,並為 Java 程式碼中的變數選取不同的顯示格式。畫面上顯示「Variables」分頁並選取框架後,請執行下列步驟:

  1. 在「Variables」清單中,在資源行中的任何位置按一下滑鼠右鍵,顯示下拉式清單。
  2. 在下拉式清單中選取「View as」,然後選取您要使用的格式。

    可用的格式取決於所選資源的資料類型。 您可能會看到下列一或多個選項:

    • 「Class」:顯示類別定義。
    • 「toString」:顯示字串格式。
    • 「Object」:顯示物件 (類別的例項) 定義。
    • 「Array」:以陣列格式顯示。
    • 「Timestamp」:以下列格式顯示日期和時間:yyyy-mm-dd hh:mm:ss。
    • 「Auto」:Android Studio 會根據資料類型選擇最適合的格式。
    • 「Binary」:使用零和一顯示二進位值。
    • 「MeasureSpec」:從父項傳遞至所選子項的值。 查看 MeasureSpec
    • 「Hex」:以十六進位值顯示。
    • 「Primitive」:以使用原始資料類型的數值顯示。
    • 「Integer」:顯示 Integer 類型的數值。

您可以按照下列方式建立自訂格式 (資料類型轉譯器):

  1. 在資源值上按一下滑鼠右鍵。
  2. 選取「View as」
  3. 選取「Create」,系統會隨即顯示「Java Data Type Renderers」對話方塊。
  4. 按照「Java Data type renderers」的說明操作。