Dalvik 和 ART 有什麼區別?深扒 Android 虛擬機器發展史,真相卻出乎意料!

guanpj發表於2019-03-04

自 2008 年 9 月 23 日對外發布第一個版本 Android 1.0 以來,在摩爾定律安迪比爾定律的共同作用下,Android 系統以每年至少一次重大更新(2016 年至今每年一次)速度進行迭代,在進行版本迭代的過程中,Android 虛擬機器的發展不可忽視。

Android 誕生之初

在 Android 系統初期,不同於 Java 平臺使用 JVM 載入位元組碼檔案(.class),Android 系統由 Dalvik 擔任虛擬機器的角色,每次執行程式的時候,Dalvik 負責載入 dex/odex 檔案並解析成機器碼交由系統呼叫。

Android 2.2 —— JIT 首次登場

為了適應硬體速度的提升,Android 系統系統也在不斷更新,單一的 Dalvik 虛擬機器已經漸漸地滿足系統的要求了,2010 年 5 月 20 日,Google 釋出 Android 2.2(Froyo凍酸奶),在這個版本中,Google 在 Android 虛擬中加入了 JIT 編譯器(Just-In-Time Compiler)。

和其他大多數 JVM 一樣,Dalvik 使用 JIT 進行即時編譯,藉助 Java HotSpot VM,JIT 編譯器可以對執行次數頻繁的 dex/odex 程式碼進行編譯與優化,將 dex/odex 中的 Dalvik Code(Smali 指令集)翻譯成相當精簡的 Native Code 去執行,JIT 的引入使得 Dalvik 的效能提升了 3~6 倍。

但是 JIT 模式的缺點也不容忽視:

  • 每次啟動應用都需要重新編譯
  • 執行時比較耗電,造成電池額外的開銷

JIT

Andorid 4.4 —— ART 和 AOT

2013 年 10 月 31 日,Google 釋出 Android 4.4(奇巧Kitkat),帶來了全新的虛擬機器執行環境 ART(Android RunTime)的預覽版和全新的編譯策略 AOT(Ahead-of-time),需要注意的是,彼時 ART 是和 Dalvik 共存的,使用者可以在兩者之間進行選擇(感覺怪怪的,使用者可是小透明啊)。

Android 5.0 —— ART 全面取代 Dalvik

2014 年 10 月 16 日,Google 釋出 Android 5.0(棒棒糖Lollipop),ART 全面取代 Dalvik 成為 Android 虛擬機器執行環境,至此,Dalvik 退出歷史舞臺,AOT 也成為唯一的編譯模式。

AOT 和 JIT 的不同之處在於:JIT 是在執行時進行編譯,是動態編譯,並且每次執行程式的時候都需要對 odex 重新進行編譯;而 AOT 是靜態編譯,應用在安裝的時候會啟動 dex2oat 過程把 dex 預編譯成 ELF 檔案,每次執行程式的時候不用重新編譯,是真正意義上的本地應用。

ART_Dalvik

另外,相比於 Dalvik,ART 對 Garbage Collection(GC)過程的也進行了改進:

  1. 只有一次 GC 暫停(Dalvik 需要兩次)
  2. 在 GC 保持暫停狀態期間並行處理
  3. 在清理最近分配的短時物件這種特殊情況中,回收器的總 GC 時間更短
  4. 優化了垃圾回收的工效,能夠更加及時地進行並行垃圾回收,這使得 GC_FOR_ALLOC 事件在典型用例中極為罕見
  5. 壓縮 GC 以減少後臺記憶體使用和碎片

AOT 模式解決了應用啟動和執行速度和耗電問題的同時也帶來了另外兩個問題:

  • 應用安裝和系統升級之後的應用優化比較耗時
  • 優化後的檔案會佔用額外的儲存空間

AOT

這也給 Android 系統後續的優化埋下了伏筆。

Android 7.0 —— JIT 迴歸

用過 Android 手機的人應該都知道,在 Android 5.x 和 6.x 的機器上,系統每次 OTA 升級完成重啟的時候都會有個應用優化的過程,這個過程就是剛才所說的 dex2oat 過程,這個過程比較耗時並且會佔用額外的儲存空間。

2016 年 8 月 22 日,Google 釋出 Android 7.0(牛軋糖Nougat),JIT 編譯器迴歸,形成 AOT/JIT 混合編譯模式,這種混合編譯模式的特點是:

  • 應用在安裝的時候 dex 不會被編譯
  • 應用在執行時 dex 檔案先通過解析器(Interpreter)後會被直接執行(這一步驟跟 Android 2.2 - Android 4.4之前的行為一致),與此同時,熱點函式(Hot Code)會被識別並被 JIT 編譯後儲存在 jit code cache 中並生成 profile 檔案以記錄熱點函式的資訊。
  • 手機進入 IDLE(空閒) 或者 Charging(充電) 狀態的時候,系統會掃描 App 目錄下的 profile 檔案並執行 AOT 過程進行編譯。

可以看出,混合編譯模式綜合了 AOT 和 JIT 的各種優點,使得應用在安裝速度加快的同時,執行速度、儲存空間和耗電量等指標都得到了優化。

AOT_JIT

總結

Android 系統從誕生到現在,經歷了幾次重要更新,最終選擇了折衷的方案,使得系統的安裝和執行的時候各項指標都得到了優化,至此,Android 虛擬機器的發展程式告一段落。但是,隨著硬體效能的不斷提升,相信谷歌的腳步不會就此停止,期待谷歌能在未來給我們不斷帶來驚喜。

參考文章/視訊

www.youtube.com/watch?v=TCJ…

source.android.com/devices/tec…

www.jianshu.com/p/9a3a4eb32…

zh.wikipedia.org/wiki/Androi…

如果你對文章內容有不同意見,歡迎留言,我們一同探討。

相關文章