Android 知識:JVM、DVM、ART的區別
JVM、DVM、ART的區別
Android底層學習必須要了解一下java的虛擬機器JVM,以及Android的虛擬機器DVM(Dalvik VM) 以及ART。
實際上Android的DVM以及ART都不是JVM的一種,因為它們沒有遵從JVM的規範。
廢話不多說,先分析一下JVM
JVM
JVM是整個java平臺的基石,是java語言編譯程式碼的執行平臺。
我們先來看看JVM的結構(面試必問:JVM記憶體模型)

image
可以看出JVM結構包含 執行時資料區 , 執行引擎 , 本地方法庫 , 本地方法介面 組成。其中類載入子系統並不屬於JVM虛擬機器的內部結構。
1.類的生命週期
Java檔案被編譯後生成Class檔案,這種二進位制格式檔案不依賴於特定硬體和作業系統。每一個Class檔案都對應著唯一的類或者介面定義資訊。無論任何語言只要能編譯成Class檔案,都能被Java虛擬機器識別並執行。
一個Java檔案被載入到Java虛擬機器記憶體中到從記憶體中解除安裝的過程被稱為 類的生命週期 。類的生命週期包括: 載入 、 連結 、 初始化 、 使用 、 解除安裝 ,其中連結包括了三個階段: 驗證 , 準備 , 解析 。因此類的生命週期包括了7個階段。
接下來大致介紹一下各個階段的工作:
1) 載入 :查詢並載入Class檔案。
2) 連結 :包括驗證、準備、和解析。
驗證:確保被匯入型別的正確性
準備:為類的靜態欄位分配欄位,並使用預設值初始化這個欄位
解析:虛擬機器將常量池內的符號引用替換為直接引用
3) 初始化 :將類變數初始化為正確的初始值
其他的就是使用和解除安裝,不必多說。
2.執行時資料區域
也就是面試常問的JVM記憶體模型,主要分為 程式計數器 , 棧 , 堆 , 方法區 和 本地方法區 。
1)程式計數器:
為保證程式能夠連續的執行下去,處理器必須具有某些手段來確定下一條指令的地址。程式計數器就起到了這個作用。 程式計數器 (Program Counter Register)也叫作PC暫存器,是一塊較小的記憶體空間。在虛擬機器概念模型中,位元組碼直譯器的工作就是通過改變程式計數器來選取下一條需要執行的位元組碼指令。Java虛擬機器的多執行緒是通過輪流切換並分配處理器執行時間的方式來實現的,在一個確定的時刻只有一個處理器執行一條執行緒中的指令,為了執行緒在切換後能回覆到正確的執行為止,每個執行緒都會有一個獨立的程式計數器。因此,程式計數器是 執行緒私有 的。
程式計數器是Java虛擬機器規範中 唯一沒有規定OutOfMemoryError情況 的資料區域。
2)Java虛擬機器棧:
每一條Java虛擬機器執行緒都有一個 執行緒私有 的Java虛擬機器棧(Java Virtual Machine Stacks)。它的生命週期與執行緒相同。Java虛擬機器棧儲存執行緒中的Java方法呼叫的狀態,包括區域性變數、引數、返回值以及運算的中間結果。一個Java虛擬機器棧包括多個 棧幀 ,一個棧幀用來儲存區域性變量表、運算元棧、動態連結、方法出口等資訊。當執行緒呼叫一個Java方法的時候,虛擬機器壓入一個新的棧幀到該執行緒的Java虛擬機器棧中,當該方法執行完成後,這個棧幀就從java虛擬機器棧中彈出。
Java虛擬機器棧規定了兩種異常情況
1:如果執行緒請求分配的棧容量超過Java虛擬機器所允許的最大容量,會丟擲StackOverflowError。
2:如果Java虛擬機器棧可以動態擴充套件,但是無法申請到足夠的記憶體,或者在建立新的執行緒時沒有足夠的記憶體去建立對應的Java虛擬機器棧,則會丟擲OutOfMemoryError。
3)本地方法棧
Java虛擬機器實現可能需要C Stacks來支援Native語言,這個C Stacks就是本地方法棧(Native Method Stack)。與Java虛擬機器棧累死,只不過本地方法棧是用來支援Native方法的。
4)Java堆
Java堆(Java Heap)是被 所有執行緒共享 的執行時記憶體區域。Java堆用來存放物件例項,幾乎所有的物件例項都會在這裡分配記憶體。Java堆儲存的物件被垃圾收集器管理,這些受管理的物件無法顯式的銷燬。
5)方法區
方法區(Method Area)是被 所有執行緒共享 的執行時記憶體區域。用來儲存已經被Java虛擬機器載入的類的結構資訊,包括執行時常量池、欄位、方法資訊、靜態變數等資料。方法區是Java堆的邏輯組成部分,它一樣在物理上不需要連續,並且可以選擇在方法區中不實現垃圾收集。
Dalvik虛擬機器
Dalvik虛擬機器(Dalvik Virtual Machine),簡稱Dalvik VM或者DVM。
為什麼開篇說DVM不屬於JVM的範疇,下面給出答案。
DVM與JVM的區別
1)基於的架構不同
JVM基於棧,意味著需要去棧中讀寫資料,所需要的指令會更多,這樣會導致速度變慢,對於效能有限的移動裝置顯然不合適。DVM是基於暫存器的,它沒有基於棧的虛擬機器在複製資料時而使用大量的出入棧指令,同事指令更緊湊、簡潔。但是由於顯式的制定了運算元,所以基於暫存器的指令會比基於棧的指令要大。
2)執行位元組碼不同
JVM中,java類被編譯成一個或多個.class檔案,並打包成.jar檔案,而後JVM會通過相應的.class檔案和.jar檔案獲取相應的位元組碼。
而DVM會用dx工具把所有的class檔案打包成一個.dex檔案,然後DVM會從該.dex檔案中讀取指令和資料。這個.dex檔案將所有的.class檔案裡面所包含的資訊全部整合到了一起,這樣載入就加快了速度。
3)DVM允許在有限的記憶體中同時執行多個程序
DVM經過優化,允許在有限的記憶體中同時執行多個程序。在Android中每一個應用都執行在一個DVM例項中,每一個DVM例項都執行在一個獨立的程序空間,獨立的程序可以防止虛擬機器崩潰時所有程式都被關閉。
4)DVM由Zygote建立並初始化
在 《Android系統啟動流程》 中提到過,Zygote是一個DVM程序,同時也用來建立和初始化其他DVM程序。每當系統需要一個應用程式程序的時候,Zygote就會fork自身,快速地建立和初始化一個DVM例項,用於程式執行。對於一些只讀的系統庫,所有的DVM例項都會和Zygote共享一塊記憶體區域,節省記憶體開銷。
5)DVM有共享機制
DVM擁有預載入-共享機制,不同應用之間執行時可以共享相同的類,擁有更高的效率。而JVM機制不存在這種共享機制。不同的程式,打包以後程式都是彼此獨立的,即便是他們使用了相同的類,執行時也都是單獨載入和執行的。
6)DVM早期沒有JIT編譯器
JVM使用了JIT(Just In Time Compiler),而DVM早期沒有使用JIT編譯器。早期DVM執行程式碼,都需要直譯器將dex程式碼編譯成機器碼,然後交給系統處理,效率不是很高。Android 2.2之後開始為DVM使用了JIT編譯器,它會對多次執行的程式碼(熱點程式碼)進行編譯,生成相當精簡的本地機器碼(Native Code),這樣在下次執行到相同的邏輯時,直接使用編譯好的機器碼即可。需要注意的是,應用程式每次重新執行的時候,都需要重做這個編譯工作。
ART虛擬機器
ART(Android Runtime)虛擬機器是Android 4.4釋出的,用來替換Dalvik虛擬機器。Android 4.4預設還是DVM,但是可以在開發者選項中切換成ART。在Android 5.0之後預設採用了ART,從此DVM退出了歷史舞臺。
ART與DVM的區別
1)前文了解到,DVM中的應用每次執行時,位元組碼都需要通過JIT編譯器編譯為機器碼,這樣會使應用程式的執行效率降低。而在ART中,系統安裝應用程式時會進行一次AOT(ahead of time compilation),將位元組碼預編譯成機器碼並存儲在本地,這樣應用程式每次執行時就不需要執行編譯了,會大大增加效率。但是AOT不是完美的,它的缺點主要有兩個:第一個是AOT會使安裝應用的時間變長,尤其是複雜的應用。第二個是位元組碼預先編譯成機器碼,機器碼需要儲存空間會多一些。為了解決這兩個問題,Android 7.0版本中的ART加入了JIT即時編譯器,作為AOT的一個補充。應用程式安裝時並不會將位元組碼全部編譯成機器碼,而是在系統執行中將熱點程式碼編譯成機器碼,從而縮短應用程式安裝時間,並且節省記憶體。
2)DVM是為32位CPU設計的,而ART是支援64位並且相容32位CPU,這也是DVM被淘汰的主要原因之一。
3)ART對垃圾回收機制進行了改進,比如更頻繁的執行並行垃圾收集,將GC暫停由2次減少為1次等等。
4)ART執行時堆空間劃分和DVM不同。
下面主要講一下ART對垃圾回收機制的改進:
ART垃圾回收
DVM的垃圾回收演算法採用的是標記-清除演算法(Mark-Sweep),ART改進了該演算法,並且使用了多種垃圾收集器。
1.Concurrent Mark Sweep(CMS):CMS收集器是一種獲取最短收集暫停時間為目標的收集器,採用了標記-清除演算法實現。它是完整的堆垃圾收集器。
2.Concurrent Partial Mark Sweep:部分完整的堆垃圾收集器
3.Concurrent Sticky Mark Sweep:粘性收集器,基於分代垃圾收集思想,它只能釋放上次GC以來分配的物件。這個垃圾收集器比一個完整或者部分完整的垃圾收集器掃描的更加頻繁,因為它更快而且暫停時間更短。
4.Marksweep + Semispace:肺病發的GC,複製GC用於堆轉換以及齊性空間壓縮(碎片整理)。
總結
DVM和ART知識體系完全可以寫一本書,如果想要更多的瞭解它請閱讀專業的書籍和部落格,比如老羅的部落格。