在了解 Android 運(yùn)行時(shí)之前,我們需要了解什么是運(yùn)行時(shí)環(huán)境以及一些基本概念,即 Java 虛擬機(jī)(JVM)和 Dalvik 虛擬機(jī)(DVM)的功能。
什么是運(yùn)行時(shí)?
簡(jiǎn)單來(lái)說(shuō),運(yùn)行時(shí)就是一個(gè)供操作系統(tǒng)使用的系統(tǒng),它負(fù)責(zé)將你用高級(jí)語(yǔ)言(比如 Java)編寫的代碼轉(zhuǎn)換成 CPU/處理器能夠理解的機(jī)器碼。
運(yùn)行時(shí)由你的程序運(yùn)行時(shí)所執(zhí)行的指令構(gòu)成,盡管本質(zhì)上它們不屬于程序代碼的任何一部分。
CPU (或者更通用的說(shuō)法電腦)只能夠理解機(jī)器語(yǔ)言(二進(jìn)制代碼),所以為了使程序能夠在 CPU 上運(yùn)行,就必須將它們翻譯成機(jī)器碼,這一工作由翻譯器完成。
這里按序列出歷代翻譯器:
1.匯編器
它直接將匯編語(yǔ)言翻譯成機(jī)器碼,所以它的速度非??臁?/p>
2.編譯器
它將源碼翻譯成匯編語(yǔ)言,然后再用匯編器轉(zhuǎn)換成機(jī)器碼。這種方式編譯過(guò)程很慢但是執(zhí)行速度很快。但是使用編譯器最大的問(wèn)題是編譯出來(lái)的機(jī)器碼依賴于特定的平臺(tái)。換句話說(shuō),在一臺(tái)機(jī)器上可以運(yùn)行的代碼在另一臺(tái)不同的機(jī)器上可能就無(wú)法運(yùn)行。
3.解釋器
它在執(zhí)行程序時(shí)才翻譯代碼。由于代碼翻譯是在執(zhí)行階段才發(fā)生,所以執(zhí)行速度很慢。
JAVA 代碼是怎么執(zhí)行的?
為了使代碼和平臺(tái)無(wú)關(guān),JAVA開發(fā)了 JVM,即 Java 虛擬機(jī)。它為每一個(gè)平臺(tái)開發(fā)一個(gè) JVM,也就意味著 JVM 是和平臺(tái)相關(guān)的。Java 編譯器將 .java 文件轉(zhuǎn)換成 .class文件,也就是字節(jié)碼。最終將字節(jié)碼提供給 JVM,由 JVM 將它轉(zhuǎn)換成機(jī)器碼。
這比解釋器要快但是比 C++ 編譯要慢。
Android 代碼是怎么執(zhí)行的
在 Android 中,Java 類被轉(zhuǎn)換成 DEX 字節(jié)碼。DEX 字節(jié)碼通過(guò) ART 或者 Dalvik runtime 轉(zhuǎn)換成機(jī)器碼。這里 DEX 字節(jié)碼和設(shè)備架構(gòu)無(wú)關(guān)。
Dalvik 是一個(gè)基于 JIT(Just in time)編譯的引擎。使用 Dalvik 存在一些缺點(diǎn),所以從 Android 4.4(Kitkat)開始引入了 ART 作為運(yùn)行時(shí),從 Android 5.0(Lollipop)開始 ART 就全面取代了Dalvik。Android 7.0 向 ART 中添加了一個(gè) just-in-time(JIT)編譯器,這樣就可以在應(yīng)用運(yùn)行時(shí)持續(xù)的提高其性能。
重點(diǎn):Dalvik 使用 JIT(Just in time)編譯而 ART 使用 AOT(Ahead of time)編譯。
下圖描述了 Dalvik 虛擬機(jī)和 Java 虛擬機(jī)之間的差別。

Just In Time (JIT)
使用 Dalvik JIT 編譯器,每次應(yīng)用在運(yùn)行時(shí),它實(shí)時(shí)的將一部分 Dalvik 字節(jié)碼翻譯成機(jī)器碼。在程序的執(zhí)行過(guò)程中,更多的代碼被被編譯并緩存。由于 JIT 只翻譯一部分代碼,它消耗的更少的內(nèi)存,占用的更少的物理存儲(chǔ)空間。
Ahead Of Time(AOT)
ART 內(nèi)置了一個(gè) Ahead-of-Time 編譯器。在應(yīng)用的安裝期間,他就將 DEX 字節(jié)碼翻譯成機(jī)器碼并存儲(chǔ)在設(shè)備的存儲(chǔ)器上。這個(gè)過(guò)程只在將應(yīng)用安裝到設(shè)備上時(shí)發(fā)生。由于不再需要 JIT 編譯,代碼的執(zhí)行速度要快得多。
由于 ART 直接運(yùn)行的是應(yīng)用的機(jī)器碼(native execution),它所占用的 CPU 資源要少于 使用 JIT 編譯的 Dalvik。由于占用較少的 CPU 資源也就消耗更少的電池資源。

[圖片上傳失敗...(image-cd4cec-1537924636323)]
ART 和 Dalvik 一樣使用的是相同的 DEX 字節(jié)碼。編譯好的應(yīng)用如果使用 ART 在安裝時(shí)需要額外的時(shí)間用于編譯,同時(shí)還需要更多的空間用于存儲(chǔ)編譯后的代碼。
Android 為什么要使用虛擬機(jī)?
Android 使用虛擬機(jī)作為其運(yùn)行環(huán)境是為了運(yùn)行 APK 文件構(gòu)成的 Android 應(yīng)用。它的優(yōu)點(diǎn)有:
- 應(yīng)用代碼和核心的操作系統(tǒng)分離。所以即使任意一個(gè)程序中包含惡意的代碼也不會(huì)直接影響系統(tǒng)文件。這使得 Android 操作系統(tǒng)更穩(wěn)定可靠。
- 它提高了跨平臺(tái)兼容性或者說(shuō)平臺(tái)獨(dú)立性。這意味著即使某一個(gè)應(yīng)用是在 PC 上編譯的,它也可以通過(guò)虛擬機(jī)在移動(dòng)平臺(tái)上執(zhí)行。
ART 的優(yōu)點(diǎn)
- 應(yīng)用運(yùn)行更快,因?yàn)?DEX 字節(jié)碼的翻譯在應(yīng)用安裝是就已經(jīng)完成。
- 減少應(yīng)用的啟動(dòng)時(shí)間,因?yàn)橹苯訄?zhí)行的是 native 代碼。
- 提高設(shè)備的續(xù)航能力,因?yàn)楣?jié)約了用于一行一行解釋字節(jié)碼所需要的電池。
- 改善的垃圾回收器
- 改善的開發(fā)者工具
ART 的缺點(diǎn)
- 應(yīng)用安裝需要更長(zhǎng)的時(shí)間,因?yàn)?DEX 字節(jié)碼需要在安裝時(shí)就翻譯成機(jī)器碼。
- 由于在安裝時(shí)時(shí)生成的 native 機(jī)器碼是存儲(chǔ)在內(nèi)部存儲(chǔ)器上,所以需要更多的內(nèi)部存儲(chǔ)空間。
結(jié)論
DEX 是專門為 Android 設(shè)計(jì)的一種字節(jié)碼格式,主要是為了消耗更少的內(nèi)存進(jìn)行優(yōu)化。ART 是為了在低端設(shè)備上運(yùn)行多個(gè)虛擬機(jī)而開發(fā)的,這一目的通過(guò)使用 DEX 字節(jié)碼實(shí)現(xiàn)。它使得應(yīng)用的 UI 反應(yīng)更及時(shí)。更多關(guān)于 ART 和 Dalvik 的細(xì)節(jié)可以參考Android 官方文檔。