實作 ART 即時編譯器

Android 運行時 (ART) 包含一個即時 (JIT) 編譯器,其程式碼分析功能可在 Android 應用程式運行時持續提高其效能。 JIT 編譯器補充了 ART 目前的提前 (AOT) 編譯器,提高了運行時效能、節省儲存空間並加快應用程式和系統更新。它還改進了 AOT 編譯器,避免了自動應用程式更新期間的系統減速或無線 (OTA) 更新期間應用程式的重新編譯。

儘管 JIT 和 AOT 使用具有相似最佳化集的相同編譯器,但產生的程式碼可能不相同。 JIT 利用運行時類型信息,可以更好地進行內聯,並使堆疊替換 (OSR) 編譯成為可能,所有這些都會產生略有不同的程式碼。

JIT架構

JIT架構
圖 1.JIT架構。

即時編譯

JIT 編譯涉及以下活動:

輪廓引導補償
圖 2.設定檔引導的編譯。
  1. 使用者運行應用程序,然後觸發 ART 載入.dex檔。
    • 如果.oat檔案( .dex檔案的 AOT 二進位檔案)可用,ART 會直接使用它。儘管.oat檔案會定期生成,但它們並不總是包含已編譯的程式碼(AOT 二進位)。
    • 如果.oat檔案不包含編譯程式碼,ART 將透過 JIT 和解釋器運行來執行.dex檔案。
  2. 對於任何未根據speed編譯過濾器進行編譯的應用程式(即「從應用程式中盡可能多地編譯」),都會啟用 JIT。
  3. JIT 設定檔資料轉儲到只有應用程式可以存取的系統目錄中的檔案。
  4. AOT 編譯 ( dex2oat ) 守護程式解析該檔案以驅動其編譯。

    JIT守護程式
    圖 3.JIT守護程序活動。

Google Play 服務是其他應用程式使用的範例,其行為類似於共享庫。

JIT工作流程

JIT架構
圖 4.JIT資料流。
  • 分析資訊儲存在程式碼快取中,並在記憶體壓力下進行垃圾收集。
    • 無法保證應用程式在背景時拍攝的快照將包含完整的資料(即 JIT 的所有內容)。
    • 不會嘗試確保記錄所有內容(因為這可能會影響運行時效能)。
  • 方法可以處於三種不同的狀態:
    • 解釋(dex 程式碼)
    • JIT編譯
    • AOT編譯
    如果 JIT 和 AOT 程式碼都存在(例如,由於重複的去優化),則首選 JIT 程式碼。
  • 在不影響前台應用程式效能的情況下執行 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 

注意:此命令保留本機設​​定檔資料。