Dalvik和ART編譯方式的演進以及Android N混合編譯對熱修復的影響

簡介

ART和Dalvik

Android Runtime (ART) 是 Android 上的應用和部分系統服務使用的託管式運行時。ART 及其前身 Dalvik 最初是專爲 Android 項目打造的。作爲運行時的 ART 可執行 Dalvik 可執行文件並遵循 Dex 字節碼規範。
ART 和 Dalvik 是運行 Dex 字節碼的兼容運行時,因此針對 Dalvik 開發的應用也能在 ART 環境中運作。不過,Dalvik 採用的一些技術並不適用於 ART。

JTI和AOT

在 Android 中,Java 類被轉換成 DEX 字節碼。DEX 字節碼通過 ART 或者 Dalvik 轉換成機器碼。
而DEX 字節碼 轉換成機器碼的編譯方式,ART 和 Dalvik是不同的:Dalvik 使用 JIT(Just in time)編譯而 ART 使用 AOT(Ahead of time)編譯。

Just In Time (JIT)
使用 Dalvik JIT 編譯器,每次應用在運行時,它實時的將一部分 Dalvik 字節碼翻譯成機器碼。在程序的執行過程中,更多的代碼被被編譯並緩存。由於 JIT 只翻譯一部分代碼,它消耗的更少的內存,佔用的更少的物理存儲空間。
Ahead Of Time(AOT)
ART 內置了一個 Ahead-of-Time 編譯器。在應用的安裝期間,他就將 DEX 字節碼翻譯成機器碼並存儲在設備的存儲器上。這個過程只在將應用安裝到設備上時發生。由於不再需要 JIT 編譯,代碼的執行速度要快得多。

而ART虛擬機在編譯方式在7.0之後變成了AOT+JIT混合方式。

爲啥要了解

因爲Android中的熱修復等技術會受到編譯方式的影響,導致老的熱修復方式失效。具體的影響可以看這篇對Tinker熱修復的影響,Android N混合編譯與對熱補丁影響深度解析,Android熱修復方案的兼容策略CLASS_ISPREVERIFIED問題,其他的收費的或者是功能比較少的就先不分析了。

演進和區別

Android 4.x(Interpreter + JIT)

原理:平時代碼走解釋器,但熱點trace會執行JIT進行即時編譯
優點:佔用內存少
缺點:耗電(退出App下次啓動還會重複編譯),卡頓(JIT編譯時)

Android 5.0/5.1/6.0(interpreter + AOT)

原理: 在AOT模式下,App在安裝過程時, 就會完成所有編譯。
優點: 性能好
缺點: App安裝時間長,佔用存儲空間多。

Android 7.0/7.1的ART引入了全新的Hybrid模式(Interpreter + JIT + AOT)

原理: App在安裝時不編譯, 所以安裝速度快。
在運行App時, 先走解釋器, 然後熱點函數會被識別,並被JIT進行編譯, 存儲在jit code cache, 併產生profile文件(記錄熱點函數信息)。
等手機進入charging和idle狀態下, 系統會每隔一段時間掃描App目錄下profile文件,並執行AOT編譯(Google官方稱之爲profile-guided compilation)。
不論是jit編譯的binary code, 還是AOT編譯的binary code, 它們之間的性能差別不大, 因爲它們使用同一個optimizing compiler進行編譯。
優點: App安裝速度快,佔用存儲少(只編譯熱點函數)。
缺點: 前幾次運行會較慢, 只有用戶操作得次數越多,jit 和AOT編譯後, 性能纔會跟上來。

Android 7.0/7.1/N的其他理解

Android N 引入了一種包含編譯、解釋和 JIT(Just In Time)的混合運行時,以便在安裝時間、內存佔用、電池消耗和性能之間獲得最好的折衷。

ART 是在 Android KitKat(譯者注:Android 4.0)引入並在 Lollipop(譯者注:Android 5.0)中設爲默認解決方案的主要特性之一,是當時的一種新的運行時。ART 取代了 Dalvik,但是前者與後者仍然保持了字節碼級的兼容,因爲前者仍在運行 DEX 文件。ART 的主要特徵之一就是安裝時對應用的 AOT 編譯。這種方式的主要優點就是優化產生的本地代碼性能更好,執行起來需要更少的電量。劣勢在於安裝文件所需的空間和時間。在 Lollipop 和 Marshmallow(譯者注:Android 6.0)中,大的應用需要數分鐘才能安裝完。

Android N 開發者預覽版包含了一個混合模式的運行時。應用在安裝時不做編譯,而是解釋字節碼,所以可以快速啓動。ART 中有一種新的、更快的解釋器,通過一種新的 JIT 完成,但是這種 JIT 的信息不是持久化的。取而代之的是,代碼在執行期間被分析,分析結果保存起來。然後,當設備空轉和充電的時候,ART 會執行鍼對“熱代碼”進行的基於分析的編譯,其他代碼不做編譯。爲了得到更優的代碼,ART 採用了幾種技巧包括深度內聯。

對同一個應用可以編譯數次,或者找到變“熱”的代碼路徑或者對已經編譯的代碼進行新的優化,這取決於分析器在隨後的執行中的分析數據。這個步驟仍被簡稱爲 AOT,可以理解爲“全時段的編譯”(All-Of-the-Time compilation)。

這種混合使用 AOT、解釋、JIT 的策略的全部優點如下。

  • 即使是大應用,安裝時間也能縮短到幾秒
  • 系統升級能更快地安裝,因爲不再需要優化這一步
  • 應用的內存佔用更小,有些情況下可以降低 50%
  • 改善了性能
  • 更低的電池消耗

綜上,Android 7.0/7.1上的ART是將Android 4.x的JIT和Android 5.x/6.0上的AOT結合,取長補短,從而在performance和battery之間取得某種trade off。

上邊的區別引用自-知乎的回答

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章