配置ART

本頁討論如何設定 Android 運行時 (ART) 及其編譯選項。這裡討論的主題包括系統映像預先編譯的配置、 dex2oat編譯選項以及如何權衡系統分區空間、資料分區空間和效能。

請參閱ART 和 Dalvik以及與 ART 搭配使用的 Dalvik 可執行格式。請參閱驗證 Android 運行時 (ART) 上的應用程式行為,以確保您的應用程式正常運作。

藝術如何運作

ART 使用提前 (AOT) 編譯,從 Android 7 開始,它使用 AOT 編譯、即時 (JIT) 編譯和解釋的混合組合,並且 AOT 編譯可以進行設定檔引導。所有這些執行模式的組合都是可配置的,將在本節中討論。例如,Pixel 設備配置為按以下流程工作:

  1. 應用程式最初安裝有由 Play Store 分發的 dex 元資料 ( .dm ) 文件,其中包含雲端設定檔。 ART AOT - 編譯雲端設定檔中列出的方法。或者,如果應用程式安裝時沒有 dex 元資料文件,則不會執行 AOT 編譯。
  2. 應用程式運行的前幾次,會解釋非 AOT 編譯的方法。在解釋的方法中,那些經常執行的方法會被JIT編譯。 ART 根據執行情況產生本機設定文件,並將其與雲端設定檔(如果存在)結合。
  3. 當裝置空閒並充電時,編譯守護程序會運行,根據前幾次運行期間產生的組合設定檔重新編譯應用程式。
  4. 在應用程式的後續運行中,ART 使用編譯守護程序產生的工件,與在非 AOT 編譯的方法仍被解釋或 JIT 編譯期間產生的程式碼相比,其中包含更多 AOT 編譯的程式碼。 ART 根據執行更新設定檔安裝,然後編譯守護程式的後續執行將取得該設定檔。

ART 包含一個編譯器( dex2oat工具)和一個在啟動期間載入的執行時間 ( libart.so )。 dex2oat工具採用 APK 檔案並產生執行時間載入的一個或多個編譯工件檔案。檔案的數量、副檔名和名稱可能會因版本而異,但從 Android 8 版本開始,會產生這些檔案:

  • .vdex :包含一些額外的元資料以加快驗證速度,有時還包含 APK 的未壓縮 DEX 程式碼。
  • .odex :包含 APK 中方法的 AOT 編譯程式碼。
  • .art (optional)包含APK中列出的一些字串和類別的ART內部表示,用於加速應用程式啟動。

編譯選項

ART 有兩類編譯選項:

  1. 系統ROM配置:建置系統映像時AOT編譯了哪些程式碼。
  2. 運行時配置:ART 如何在設備上編譯和運行應用程式。

編譯器過濾器

配置這兩個類別的一個核心 ART 選項是編譯器過濾器。編譯器過濾器驅動 ART 編譯 DEX 程式碼的方式,並且是傳遞給dex2oat工具的選項。從 Android 8 開始,官方支援四種濾鏡:

  • verify :僅執行 DEX 程式碼驗證(無 AOT 編譯)。
  • quicken :(直到 Android 11)運行 DEX 程式碼驗證並優化一些 DEX 指令以獲得更好的解釋器效能。
  • speed :執行 DEX 程式碼驗證並 AOT 編譯所有方法。
  • speed-profile :執行設定檔中列出的 DEX 程式碼驗證和 AOT 編譯方法。

系統ROM配置

建置系統映像時,預先安裝的程式庫和應用程式會進行 AOT 編譯。這個過程稱為dexpreopt 。只要所有依賴項(特別是引導類別路徑)保持不變,此類編譯檔案就可以使用。

注意:如果裝置進行系統模組更新,則引導類別路徑很可能在下一次更新中發生更改,這會導致所有 dexpreopt 檔案過時且無法使用。

有許多 ART 建置選項可用於配置 dexpreopt。如何配置這些選項取決於系統映像的可用儲存空間和預先安裝應用程式的數量。編譯到系統 ROM 中的 JAR/APK 可分為四大類:

  • 引導類別路徑程式碼:預設使用speed-profile檔編譯器過濾器編譯。
  • 系統伺服器程式碼(請參閱本文檔後面的PRODUCT_SYSTEM_SERVER_JARSPRODUCT_APEX_SYSTEM_SERVER_JARSPRODUCT_STANDALONE_SYSTEM_SERVER_JARSPRODUCT_APEX_STANDALONE_SYSTEM_SERVER_JARS ):
    • (Android 14 及更高版本)預設使用speed-profile編譯器過濾器進行編譯,如果未提供設定文件,則使用speed編譯器過濾器進行編譯。
    • (Android 13及更低版本)預設使用speed編譯器過濾器編譯。
    可透過PRODUCT_SYSTEM_SERVER_COMPILER_FILTER進行設定(請參閱本文檔後面的內容)。
  • 產品特定的核心應用程式(請參閱本文檔後面的PRODUCT_DEXPREOPT_SPEED_APPS ):預設使用speed編譯器過濾器進行編譯。
  • 所有其他應用程式:預設使用speed-profile編譯器過濾器進行編譯,或者如果未提供設定文件,則使用verify編譯器過濾器進行編譯。

    可透過PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER進行設定(請參閱本文檔後面的內容)。

生成檔案選項

  • WITH_DEXPREOPT
  • 是否在系統映像上安裝的 DEX 程式碼上呼叫dex2oat 。預設啟用。

  • DONT_DEXPREOPT_PREBUILTS (Android 5 及更高版本)
  • 啟用DONT_DEXPREOPT_PREBUILTS可防止預先建構被 dexpreopted。這些應用程式包含在其Android.mk中指定的include $(BUILD_PREBUILT) 。跳過可能透過 Google Play 更新的預先建置應用程式的 dexpreopt 可以節省系統映像中的空間,但會增加首次啟動時間。請注意,此選項對Android.bp中定義的預建置應用程式沒有影響。

  • PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER (Android 9 及更高版本)
  • PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER指定 dexpreopted 應用程式的預設編譯器過濾器。這些應用程式在Android.bp中定義,或包含在其Android.mk中指定的include $(BUILD_PREBUILT) 。如果未指定,則預設值為speed-profile ,或verify該值是否未指定且未提供設定檔。

  • WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY (自 Android 8 MR1 起)
  • 啟用WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY僅dexpreopt啟動類別路徑和系統伺服器jar。

  • LOCAL_DEX_PREOPT
  • 也可以透過在模組定義中指定LOCAL_DEX_PREOPT選項來在單一應用程式上啟用或停用 Dexpreopt。這對於停用可能立即接收 Google Play 更新的應用程式的 dexpreopt 非常有用,因為更新會使系統映像中的 dexpreopt 程式碼過時。這對於節省主要版本升級 OTA 的空間也很有用,因為使用者可能已經在資料分割區中擁有較新版本的應用程式。

    LOCAL_DEX_PREOPT支援值truefalse來分別啟用或停用 dexpreopt。此外,如果 dexpreopt 不應從 APK 或 JAR 檔案中刪除classes.dex文件,則可以指定nostripping 。通常,此檔案會被刪除,因為在 dexpreopt 之後不再需要它,但最後一個選項對於允許第三方 APK 簽章保持有效是必需的。

  • PRODUCT_DEX_PREOPT_BOOT_FLAGS
  • 將選項傳遞給dex2oat以控制啟動映像的編譯方式。它可用於指定自訂圖像類別清單、編譯類別清單和編譯器過濾器。

  • PRODUCT_DEX_PREOPT_DEFAULT_FLAGS
  • 將選項傳遞給dex2oat以控制除啟動映像之外的所有內容的編譯方式。

  • PRODUCT_DEX_PREOPT_MODULE_CONFIGS
  • 提供為特定模組和產品配置傳遞dex2oat選項的能力。它透過$(call add-product-dex-preopt-module-config,<modules>,<option>)在產品的device.mk檔案中設置,其中<modules>是 JAR 和 APK 檔案的LOCAL_MODULELOCAL_PACKAGE名稱的列表, 分別。

  • PRODUCT_DEXPREOPT_SPEED_APPS (自 Android 8 起)
  • 已被確定為產品核心且需要使用speed編譯器過濾器進行編譯的應用程式清單。例如,SystemUI 等持久性應用程式僅在下次重新啟動時才有機會使用設定檔引導編譯,因此產品最好讓這些應用程式始終進行 AOT 編譯。

  • PRODUCT_SYSTEM_SERVER_APPS (自 Android 8 起)
  • 系統伺服器載入的應用程式清單。這些應用程式預設使用speed編譯器過濾器進行編譯。

  • PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD (自 Android 8 起)
  • 是否在裝置上包含 ART 的調試版本。預設情況下,這對於 userdebug 和 eng 版本是啟用的。可以透過明確將該選項設為truefalse來覆寫該行為。

    預設情況下,裝置使用非偵錯版本 ( libart.so )。若要進行切換,請將系統屬性persist.sys.dalvik.vm.lib.2設定為libartd.so

  • WITH_DEXPREOPT_PIC (直到 Android 7)
  • 在 Android 5.1.0 到 Android 6.0.1 中,可以指定WITH_DEXPREOPT_PIC以啟用位置無關代碼 (PIC)。這樣,來自映像的編譯程式碼不必從/system重新定位到/data/dalvik-cache ,從而節省了資料分區中的空間。但是,會產​​生輕微的運行時影響,因為它禁用了利用位置相關程式碼的最佳化。通常,想要節省/data空間的設備應啟用 PIC 編譯。

    在Android 7.0中,預設啟用PIC編譯。

  • WITH_DEXPREOPT_BOOT_IMG_ONLY (直到 Android 7 MR1)
  • 此選項已替換為WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY ,它也預先選擇系統伺服器JAR。

  • PRODUCT_SYSTEM_SERVER_COMPILER_FILTER
  • 此選項指定係統伺服器的編譯器過濾器。

    • (Android 14 及更高版本)如果未指定,則使用speed-profile編譯器過濾器,或如果未提供設定文件,則使用speed編譯器過濾器。
    • (Android 13 及更低版本)如果未指定,則使用speed編譯器過濾器。
    • 如果設定為speed ,則使用speed編譯器過濾器。
    • 如果設定為speed-profile ,則使用speed-profile編譯器過濾器,或者如果未提供設定文件,則使用verify編譯器過濾器。
    • 如果設定為verify ,則使用verify編譯器過濾器。

  • PRODUCT_SYSTEM_SERVER_JARSPRODUCT_APEX_SYSTEM_SERVER_JARSPRODUCT_STANDALONE_SYSTEM_SERVER_JARSPRODUCT_APEX_STANDALONE_SYSTEM_SERVER_JARS
  • 以下是系統伺服器載入的 JAR 清單。 JAR 使用PRODUCT_SYSTEM_SERVER_COMPILER_FILTER指定的編譯器過濾器進行編譯

    • (必要) PRODUCT_SYSTEM_SERVER_JARS :平台上的系統伺服器類別路徑 JAR 清單(即,作為SYSTEMSERVERCLASSPATH的一部分)。需要將系統伺服器類別路徑 JAR 新增至此清單。未能將系統伺服器類別路徑 JAR 新增至清單中會導致這些 JAR 未被載入。
    • (必要) PRODUCT_APEX_SYSTEM_SERVER_JARS :隨 APEX 提供的系統伺服器類別路徑 JAR 的清單(即,作為SYSTEMSERVERCLASSPATH的一部分)。格式為<apex name>:<jar name> 。需要將 APEX 系統伺服器類別路徑 JAR 新增至此清單。未能將 APEX 系統伺服器類別路徑 JAR 新增至此清單會導致這些 JAR 無法載入。
    • (可選,Android 13 及更低版本) PRODUCT_STANDALONE_SYSTEM_SERVER_JARS :系統伺服器使用單獨的類別載入器(透過SystemServiceManager.startServiceFromJar )動態載入的 JAR 清單。將獨立系統伺服器 JAR 添加到此列表不是必需的,但強烈建議這樣做,因為它可以使 JAR 編譯並因此具有良好的運行時效能。
    • (自 Android 13 起必要) PRODUCT_APEX_STANDALONE_SYSTEM_SERVER_JARS :隨 APEX 提供的 JAR 列表,系統伺服器使用單獨的類別載入器動態載入(即透過SystemServiceManager.startServiceFromJar或聲明為<apex-system-service> )。格式為<apex name>:<jar name> 。需要將獨立 APEX 系統伺服器 JAR 新增至此清單。無法將獨立 APEX 系統伺服器 JAR 新增至此清單會導致啟動失敗。

    引導類路徑配置

    預載類別列表是 Zygote 在啟動時初始化的類別列表。這使得每個應用程式不必單獨運行這些類別初始值設定項,從而使它們能夠更快地啟動並共享記憶體中的頁面。預設情況下,預先載入的類別清單檔案位於frameworks/base/config/preloaded-classes ,它包含一個針對典型手機使用進行調整的清單。對於穿戴式裝置等其他裝置來說,這可能有所不同,必須進行相應調整。調整時要小心;當載入未使用的類別時,添加太多的類別會浪費記憶體。添加太少的類別會迫使每個應用程式必須擁有自己的副本,這又會浪費記憶體。

    範例用法(在產品的device.mk中):

    PRODUCT_COPY_FILES += <filename>:system/etc/preloaded-classes
    

    注意:您必須在繼承從build/target/product/base.mk取得預設檔案的任何產品配置 makefile 之前放置這一行。

    運行時配置

    即時選項

    以下選項僅影響 ART JIT 編譯器可用的 Android 版本。

    • dalvik.vm.usejit :是否啟用 JIT。
    • dalvik.vm.jitinitialsize (預設64K):程式碼快取的初始容量。程式碼快取將定期進行 GC,並在需要時增加。
    • dalvik.vm.jitmaxsize (預設64M):程式碼快取的最大容量。
    • dalvik.vm.jitthreshold (預設 10000):方法的「熱度」計數器需要通過的閾值,以便對此方法進行 JIT 編譯。 “熱度”計數器是運行時內部的度量標準。它包括呼叫次數、向後分支和其他因素。
    • dalvik.vm.usejitprofiles (直到 Android 13):是否啟用 JIT 設定檔;即使dalvik.vm.usejit為 false,也可以使用它。請注意,如果這是 false,則編譯器過濾器speed-profile不會 AOT 編譯任何方法,並且相當於verify 。自 Android 14 起,JIT 設定檔始終啟用且無法關閉。
    • dalvik.vm.jitprithreadweight (預設為dalvik.vm.jitthreshold / 20):應用程式 UI 執行緒的 JIT「樣本」的權重(請參閱 jitthreshold)。用於加速直接影響使用者與應用程式互動時的體驗的方法的編譯。
    • dalvik.vm.jittransitionweight (預設為dalvik.vm.jitthreshold / 10):在編譯程式碼和解釋器之間轉換的方法呼叫的權重。這有助於確保所涉及的方法被編譯以最小化轉換(這是昂貴的)。

    Dex2oat 選項

    這些選項會影響裝置上編譯(又稱dexopt ),其中一些也會影響 dexpreopt,而上面的系統 ROM 配置部分中討論的選項僅影響 dexpreopt。

    控制資源使用的選項:

    • dalvik.vm.image-dex2oat-threads / dalvik.vm.image-dex2oat-cpu-set (直到 Android 11):用於啟動映像的執行緒數和 CPU 核心集(見下文)。
    • dalvik.vm.boot-dex2oat-threads / dalvik.vm.boot-dex2oat-cpu-set
      • (直到 Android 11)在啟動期間用於除啟動映像之外的所有內容的執行緒數和 CPU 核心集(見下文)。
      • (自 Android 12 起)在啟動期間用於所有內容(包括啟動映像)的執行緒數和 CPU 核心集(見下文)。
        • 具體來說,從 Android 14 開始,這對應於 ART Service 中的優先類別PRIORITY_BOOT
    • dalvik.vm.restore-dex2oat-threads / dalvik.vm.restore-dex2oat-cpu-set
      • (從 Android 11 開始,直到 Android 13)用於從雲端備份還原的執行緒數和 CPU 核心集(見下文)。
      • (自 Android 14 起)用於比正常情況對延遲更敏感的所有操作(包括從雲端備份還原)的執行緒數和 CPU 核心集(見下文)。
        • 具體來說,這對應於 ART 服務中的優先類別PRIORITY_INTERACTIVE_FAST
    • dalvik.vm.background-dex2oat-threads / dalvik.vm.background-dex2oat-cpu-set (自 Android 14 起):在背景使用的執行緒數和 CPU 核心集(見下文)。
      • 具體來說,這對應於ART服務中的優先類別PRIORITY_BACKGROUND
    • dalvik.vm.dex2oat-threads / dalvik.vm.dex2oat-cpu-set :用於其他所有操作的執行緒數和 CPU 核心集。

    一組 CPU 核心應指定為以逗號分隔的 CPU id 清單。例如,要在 CPU 核心 0-3 上的 dex2oat 上運行,請設定:

    dalvik.vm.dex2oat-cpu-set=0,1,2,3
    

    在設定 CPU 親和性屬性時,我們建議匹配 dex2oat 執行緒數的對應屬性以匹配所選的 CPU 數,以避免不必要的記憶體和 I/O 爭用:

    dalvik.vm.dex2oat-cpu-set=0,1,2,3
    dalvik.vm.dex2oat-threads=4
    

    除了上面的系統屬性之外,您還可以使用任務設定檔來控制 dex2oat 的資源使用情況(請參閱Cgroup 抽象層)。

    支援的任務設定檔有:

    • Dex2OatBackground (自 Android 14 起)(預設繼承Dex2OatBootComplete ):控制在背景使用的資源。
      • 具體來說,這對應於ART服務中的優先類別PRIORITY_BACKGROUND
    • Dex2OatBootComplete
      • (直到 Android 13)控制啟動後用於所有操作的資源。
      • (自 Android 14 起)控制啟動後用於所有操作的資源,而不是在背景。
        • 具體來說,這對應於 ART 服務中的優先類別PRIORITY_INTERACTIVE_FASTPRIORITY_INTERACTIVE

    當系統屬性和任務設定檔都指定時,兩者都會生效。

    控制堆大小的選項:

    • dalvik.vm.image-dex2oat-Xms :啟動映像的初始堆疊大小。
    • dalvik.vm.image-dex2oat-Xmx :啟動映像的最大堆疊大小。
    • dalvik.vm.dex2oat-Xms :其他所有內容的初始堆大小。
    • dalvik.vm.dex2oat-Xmx :其他所有內容的最大堆大小。

    不應減少控制dex2oat的初始和最大堆大小的選項,因為它們可能會限制可以編譯的應用程式。

    控制編譯器過濾器的選項:

    • dalvik.vm.image-dex2oat-filter (Android 11 之前):啟動映像的編譯器過濾器。自 Android 12 起,啟動映像的編譯器過濾器始終是speed-profile且無法變更。
    • dalvik.vm.systemservercompilerfilter (自 Android 13 起):系統伺服器的編譯器過濾器。請參閱PRODUCT_SYSTEM_SERVER_COMPILER_FILTER
    • dalvik.vm.systemuicompilerfilter (自 Android 13 起):系統 UI 套件的編譯器過濾器。
    • dalvik.vm.dex2oat-filter (Android 6 之前):用於其他所有內容的編譯器過濾器。
    • pm.dexopt.<reason> (自 Android 7 起):用於其他所有內容的編譯器過濾器。請參閱 Android 14 及更高版本的ART 服務配置,或 Android 13 及更低版本的套件管理器配置

    用於控制除啟動映像之外的所有內容的編譯的其他選項:

    • dalvik.vm.dex2oat-very-large (自 Android 7.1 起):停用 AOT 編譯的最小總 dex 檔案大小(以位元組為單位)。
    • dalvik.vm.dex2oat-swap (自 Android 7.1 起)(預設值:true):允許使用 dex2oat 的交換檔案。這可以幫助避免記憶體不足崩潰。請注意,即使開啟此選項,dex2oat 也只會在某些條件下使用交換文件,例如當 dex 文件數量很大時,且條件可能會發生變化。
    • dalvik.vm.ps-min-first-save-ms (自 Android 12 起):首次啟動應用程式時,執行時產生應用程式設定檔之前等待的最短時間。
    • dalvik.vm.ps-min-save-period-ms (自 Android 12 起):更新應用程式設定檔之前等待的最短時間。
    • dalvik.vm.dex2oat64.enabled (自Android 11起)(預設值:false):是否使用64位元版本的dex2oat。
    • dalvik.vm.bgdexopt.new-classes-percent (自 Android 12 起)(預設值:20):設定檔中觸發重新編譯的新類別的最小百分比(介於 0 到 100 之間)。僅適用於設定檔引導編譯( speed-profile ),通常在背景 dexopt 期間。請注意,除了百分比閾值之外,還有至少 50 個新類別的閾值,且該閾值無法配置。
    • dalvik.vm.bgdexopt.new-methods-percent (自 Android 12 起)(預設值:20):設定檔中觸發重新編譯的新方法的最小百分比(介於 0 到 100 之間)。僅適用於設定檔引導編譯( speed-profile ),通常在背景 dexopt 期間。請注意,除了百分比閾值之外,還有至少 100 個新方法的閾值,且該閾值無法配置。
    • dalvik.vm.dex2oat-max-image-block-size (自 Android 10 起)(預設值:524288)壓縮影像的最大實體區塊大小。大圖像被分割成一組固體塊,使得沒有塊大於最大尺寸。
    • dalvik.vm.dex2oat-resolve-startup-strings (自 Android 10 起)(預設值:true)如果為 true,則使 dex2oat 解析從設定檔中標記為「startup」的方法引用的所有 const-string。
    • debug.generate-debug-info (預設值: false) 是否產生用於本機偵錯的偵錯訊息,例如堆疊展開式資訊、ELF 符號和 dwarf 部分。
    • dalvik.vm.dex2oat-minidebuginfo (自 Android 9 起)(預設值:true)是否會產生列印回溯所需的最少量的 LZMA 壓縮偵錯資訊。

    藝術服務選項

    自 Android 14 起,應用程式的裝置上 AOT 編譯(又稱 dexopt)由 ART 服務處理。有關配置 ART 服務的信息,請參閱ART 服務配置

    套件管理器選項

    在 Android 14 之前,應用程式的裝置上 AOT 編譯(又稱 dexopt)由套件管理器處理。有關為 dexopt 配置套件管理器的信息,請參閱套件管理器配置

    A/B具體配置

    ROM配置

    從 Android 7.0 開始,裝置可以使用兩個系統分割區來啟用A/B 系統更新。為了節省系統分割區大小,可以將預先選擇的檔案安裝在未使用的第二個系統分割區中。然後,它們會在首次啟動時複製到資料分區。

    範例用法(在device-common.mk中):

    PRODUCT_PACKAGES += \
         cppreopts.sh
    PRODUCT_PROPERTY_OVERRIDES += \
         ro.cp_system_other_odex=1
    

    在設備的BoardConfig.mk中:

    BOARD_USES_SYSTEM_OTHER_ODEX := true
    

    請注意,啟動類別路徑程式碼、系統伺服器程式碼和特定於產品的核心應用程式始終編譯到系統分區。預設情況下,所有其他應用程式都會編譯到未使用的第二個系統分區。這可以透過SYSTEM_OTHER_ODEX_FILTER進行控制,預設值為:

    SYSTEM_OTHER_ODEX_FILTER ?= app/% priv-app/%
    

    後台 OTA dexopt

    在啟用 A/B 的裝置上,可以在使用新系統映像重新啟動之前在背景編譯應用程式。請參閱背景應用程式編譯,以選擇性地將編譯腳本和二進位檔案包含在系統映像中。用於此編譯的編譯過濾器由以下命令控制:

    pm.dexopt.ab-ota=speed-profile
    

    我們建議使用speed-profile來利用設定檔引導編譯並節省儲存空間。

    JDWP 選項

    userdebug 建置中的 Java 偵錯線協定 (JDWP) 執行緒建立是透過persist.debug.dalvik.vm.jdwp.enabled系統屬性控制的。預設情況下,未設定此屬性,並且僅為可偵錯應用程式建立 JDWP 執行緒。若要為可偵錯和不可偵錯應用程式啟用 JDWP 線程,請將persist.debug.dalvik.vm.jdwp.enabled設為1 。必須重新啟動設備才能使屬性變更生效。

    要在 userdebug 版本上調試不可調試的應用程序,請透過執行以下命令啟用 JDWP:

      adb shell setprop persist.debug.dalvik.vm.jdwp.enabled 1
      adb reboot
      
    對於運行 Android 13 及更低版本的設備,運行時會在 userdebug 版本上為可偵錯和不可偵錯的應用程式建立 JDWP 執行緒。這意味著可以在 userdebug 版本上附加偵錯器或分析任何應用程式。