Android ART dex2oat 淺析


一、什么是dex2oat

Dex2oat (dalvik excutable file to optimized art file) ,是一個對 dex 文件進行編譯優化的程序,在我們的 Android 手機中的位置是 /system/bin/dex2oat,對應的源碼路徑為 android/art/dex2oat/dex2oat.cc,通過編譯優化,可以提升用戶日常的使用體驗(包含安裝速度、啟動速度、應用使用過程中的流暢度等),是 Android Art Runtime 中的一個重要的模塊, 本文我們一起來了解下 dex2oat 的功能以及常用的場景。

二、為什么要進行dex2oat轉換?

眾所周知, Android 虛擬機可以識別的是dex文件,應用使用過程中如果每次將dex文件加載進行內存,解釋性執行字節碼,效率會很低, 嚴重影響用戶體驗。通過dex2oat 優化后, 可以在系統運行之前利用合適的時機將dex文件字節碼提前轉化為虛擬機可以執行運行的機器碼,后續直接從效率更高的機器碼中運行,則運行階段更加流暢,優化用戶體驗。

Dex2oat的主要觸發場景

三、幾種dex2oat 相關的文件

Dex文件:Dex文件是Android 虛擬機識別的一種可執行文件,我們可以解壓一個apk, 獲取其中的class.dex文件, 通過dexdump 命令工具對dex 文件進行解析,查看文件內容,更多格式說明查看參考資料 1。

Oat文件:art執行的文件,dex2oat程序編譯dex文件的產物。我們可以通過oatdump 查看oat文件具體內容。

Odex文件: Optimizied dexfile, dex文件已經dexopt操作優化后的產物,和dex文件類似,使用了一些優化操作碼。

Art文件:Image文件,記錄應用啟動熱點函數相關地址,方便尋址。

Vdex文件:Verified dex,主要包含dex和quicken info信息。Andorid 8.0新增機制產生的文件,其目的主要是為了跳過verified流程,減少dex2oat執行時間。

四、如何使用Dex2oat

4.1  Dex2oat用法

Dex2oat工具的常用參數如下:

4.2  Dex2oat日志解析

從日志中可以看出,在dex2oat發起時具體的編譯類型、線程數以及編譯原因等等。

常見的編譯類型:verify、quicken、space-profile、space、speed-profile、speed、everything, 具體效果從字面上比較好理解, 越后面的類型編譯時間越長,占用的空間也越大,運行時打開速度也越快,典型空間換時間思路的體現,其中profile類型的編譯方式主要是根據JIT運行過程中熱點函數的情況進行編譯,JIT機制不進行展開,可以查閱相關資料。

4.3  和dex2oat相關的系統配置

[pm.dexopt.ab-ota]: [speed-profile]

[pm.dexopt.bg-dexopt]: [speed-profile]

[pm.dexopt.boot]: [verify]

[pm.dexopt.first-boot]: [quicken]

[pm.dexopt.inactive]: [verify]

[pm.dexopt.install]: [speed-profile]

[pm.dexopt.shared]: [speed]

4.4  如何手動發起dex2oat操作

通過以上介紹參數含義后,我們可以在adb shell 下通過命令行方式直接發起dex2oat操作,例如強制編譯微信:

adb shell cmd package compile -m speed-profile -f com.tencent.mm

清除配置文件數據並移除經過編譯的代碼:

adb shell cmd package compile --reset com.tencent.mm

下面對具體調用的流程進行分析。

五、Dex2oat 流程分析

本次分析基於Android Q 代碼。上述觸發場景主要涉及PackageManagerService , 所以從該服務作為入口,分析dex2oat的相關流程。

應用在發起dex2oat時,主要通過PMS中接口調用installd觸發的,相關調用函數performDexOpt ,該函數在上述應用安裝以及啟動的時候都會涉及,所以主要查看下這個函數的調用流程,詳見代碼:

傳入參數DexoptOptions , 可以通過該參數指定編譯包名,編譯類型以及標志,返回編譯是否成功。常見編譯標志位:

接下來的調用流程:

以上是Framework中Dex2oat 的調用流程, 感興趣的同學可以跟蹤代碼查看具體細節。

系統經過installd 的dexopt編譯,通常會利用一些關鍵的日志查看dex2oat相關的信息, 比如計算dex2oat運行耗時以及最終的編譯狀態。

Installd dexopt代碼小結:

1.檢測dexopt  classloader context 和相關的flag。

2.解析傳入參數,生成dex2oat 命令, 最后通過RunDex2Oat 執行。 

常見的dalvik參數控制屬性值,更多標志位參考詳見參考資料2:

經過上述命令,最終調用到底層libart中相關代碼,下面我們查看dex2oat調用的流程圖, 了解dex2oat的相關流程。

流程圖

Dex2oat邏輯小結:

1. 處理命令行參數;

2. 判斷dex2oat的setup是否完成;

3. 根據是否為image類型,分別調用CompileImage或CompileApp的處理,CompileImage和CompileApp的主要功能邏輯類似,主要通過CompilerDriver對dexfile 進行編譯。

六、Dex2oat常見修改思路

前面介紹了dex2oat一些優化以及相關的流程,雖然能夠提高系統的流暢度,如果在不合適的時機發起,很有可能影響到其他用戶操作,需要針對這一類情況進行修改。

以下是常見的修改思路:

1. 根據場景和負載情況調整dex2oat 編譯參數,如編譯類型,編譯線程數量等。

2. 調整boot.img編譯資源,預加載資源文件列表。

3. 后台並行編譯。在系統空閑或者首次加載dex文件的時候預先觸發dex2oat流程,從而加快后續使用dex文件的速度。

舉例:后台應用安裝導致大量資源被dex2oat占用導致前台進程卡頓

dex2oat 優化后雖然能夠增加應用運行的流暢度, 但是如果在短時間內大量發起則會影響用戶界面操作, 造成負面的影響。所以發現應用是因為后台自動更新時, 則可以限制dex2oat運行的線程數量,盡可能的減少對前面進程的影響。

七、總結

本文從dex2oat日志輸出和使用命令出發,介紹了dex2oat常用的場景以及相關的調用流程,以此為根據簡單討論了常見dex2oat優化方面的思路,希望能起到拋磚引玉的作用,加深讀者對dex2oat的原理流程的了解。

參考資料

1.https://source.android.google.cn/devices/tech/dalvik/dex-format

2.https://source.android.com/devices/tech/dalvik/configure#runtime_configuration

3.https://source.android.com/devices/tech/dalvik

4.https://blog.csdn.net/cosmoslhf/article/details/40380559

掃描關注
“內核工匠”微信公眾號
Linux 內核黑科技 | 技術文章 | 精選教程

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM