Android 執行階段 (ART) 包含即時 (JIT) 編譯器,可透過程式碼剖析持續改善 Android 應用程式執行時的效能。JIT 編譯器可補足 ART 目前的預先 (AOT) 編譯器,並改善執行階段效能、節省儲存空間,以及加快應用程式和系統更新速度。這個程式庫也能改善 AOT 編譯器的效能,避免在自動更新應用程式期間,或避免在無線更新 (OTA) 期間重新編譯應用程式時,降低系統運作速度。
雖然 JIT 和 AOT 使用相同的編譯器,且採用類似的最佳化組合,但產生的程式碼可能不盡相同。JIT 會使用執行階段類型資訊,可進行更佳的內嵌作業,並可進行堆疊替換 (OSR) 編譯,所有這些都會產生略有不同的程式碼。
JIT 架構
JIT 編譯
JIT 編譯涉及下列活動:
- 使用者執行應用程式,然後觸發 ART 載入
.dex
檔案。- 如果
.oat
檔案 (.dex
檔案的 AOT 二進位檔) 可用,ART 會直接使用該檔案。雖然.oat
檔案會定期產生,但不一定會包含編譯的程式碼 (AOT 二進位檔)。 - 如果
.oat
檔案不含編譯程式碼,ART 會透過 JIT 和轉譯器執行.dex
檔案。
- 如果
- 任何未根據
speed
編譯篩選器編譯的應用程式,都會啟用 JIT (也就是「盡可能從應用程式編譯」)。 - JIT 設定檔資料會轉儲至系統目錄中的檔案,該檔案只有應用程式可存取。
- AOT 編譯 (
dex2oat
) 守護程式會剖析該檔案,以便驅動編譯作業。
圖 3. JIT 守護程式活動。
Google Play 服務是其他應用程式使用的例子,運作方式與共用程式庫類似。
JIT 工作流程
- 分析資訊會儲存在程式碼快取中,並在記憶體壓力下進行垃圾收集。
- 應用程式在背景執行時拍攝的快照不一定會包含完整資料 (也就是 JITed 的所有內容)。
- 系統不會嘗試確保所有內容都已記錄 (因為這可能會影響執行階段效能)。
- 方法可處於三種狀態:
- 解譯 (dex 程式碼)
- JIT 編譯
- AOT 編譯
- 如要在不影響前景應用程式效能的情況下執行 JIT,記憶體需求取決於相關應用程式。大型應用程式需要的記憶體比小型應用程式多。一般來說,大型應用程式會在 4 MB 左右穩定下來。
開啟 JIT 記錄功能
如要開啟 JIT 記錄功能,請執行下列指令:
adb root
adb shell stop
adb shell setprop dalvik.vm.extra-opts -verbose:jit
adb shell start
停用 JIT
如要停用 JIT,請執行下列指令:
adb root
adb shell stop
adb shell setprop dalvik.vm.usejit false
adb shell start
強制編譯
如要強制執行編譯,請執行下列指令:
adb shell cmd package compile
強制編譯特定套件的常見用途:
- 以設定檔為依據:
adb shell cmd package compile -m speed-profile -f my-package
- 完整:
adb shell cmd package compile -m speed -f my-package
強制編譯所有套件的常見用途:
- 以設定檔為基礎:
adb shell cmd package compile -m speed-profile -f -a
- 完整:
adb shell cmd package compile -m speed -f -a
清除設定檔資料
Android 13 以下版本
如要清除本機設定檔資料並移除已編譯的程式碼,請執行下列指令:
adb shell pm compile --reset
在 Android 14 以上版本
如果只要清除本機設定檔資料,請按照以下步驟操作:
adb shell pm art clear-app-profiles
注意:與 Android 13 以下版本的指令不同,這個指令不會清除透過應用程式安裝的外部設定檔資料 (".dm")。
如要清除本機設定檔資料,並移除由本機設定檔資料產生的編譯代碼 (也就是將其重設為安裝狀態),請執行下列指令:
adb shell pm compile --reset
注意:這個指令不會移除隨應用程式一併安裝的外部設定檔資料 (`.dm`) 產生的已編譯程式碼。
如要清除所有已編譯的程式碼,請執行下列指令:
adb shell cmd package compile -m verify -f
注意:這個指令會保留本機設定檔資料。