1 概論
1.1 JVM概念
???????JVM是Java Virtual Machine的簡稱垮卓,本質(zhì)上就是一個軟件,是計算機(jī)硬件的一層軟件抽象师幕,在這之上才能夠運行Java程序粟按,JAVA在編譯后會生成類似于匯編語言的JVM字節(jié)碼,與C語言編譯后產(chǎn)生的匯編語言不同的是,C編譯成的匯編語言會直接在硬件上跑钾怔,但JAVA編譯后生成的字節(jié)碼是在JVM上跑碱呼,需要由JVM把字節(jié)碼翻譯成機(jī)器指令,才能使JAVA程序跑起來宗侦。
???????JVM運行在操作系統(tǒng)上愚臀,屏蔽了底層實現(xiàn)的差異,從而有了JAVA吹噓的平臺獨立性和Write Once Run Anywhere矾利。根據(jù)JVM規(guī)范實現(xiàn)的具體虛擬機(jī)有幾十種姑裂,主流的JVM包括Hotspot、Jikes RVM等男旗,都是用C/C++和匯編編寫的舶斧,每個JRE編譯的時候針對每個平臺編譯,因此下載JRE(JVM察皇、Java核心類庫和支持文件)的時候是分平臺的茴厉,JVM的作用是把平臺無關(guān)的.class里面的字節(jié)碼翻譯成平臺相關(guān)的機(jī)器碼,來實現(xiàn)跨平臺什荣。
1.2 DVM概念
???????DVM是Dalvik Virtual Machine的縮寫矾缓,是Android4.4及以前使用的虛擬機(jī),所有android程序都運行在android系統(tǒng)進(jìn)程里稻爬,每個進(jìn)程對應(yīng)著一個Dalvik虛擬機(jī)實例嗜闻。JVM和DVM都提供了對象生命周期管理,堆棧管理桅锄,線程管理琉雳,安全和異常管理及垃圾回收等重要功能,各自擁有一套完整的指令系統(tǒng)友瘤。
???????APK在打包的過程中會先將java等源碼通過javac編譯成.class文件翠肘,然后通過android的dx工具將.class文件轉(zhuǎn)換成Dalvik虛擬機(jī)能夠執(zhí)行的.dex文件。Dalvik虛擬機(jī)在應(yīng)用程序啟動時辫秧,會將.dex文件轉(zhuǎn)換成快速運行的機(jī)器碼進(jìn)行執(zhí)行锯茄。
1.3 ART概念
???????在android5.0及后續(xù)版本中,Google采用了ART正式取代了以往的Dalvik虛擬機(jī)茶没,ART虛擬機(jī)會將.dex文件轉(zhuǎn)化為可直接運行的.oat文件。
1.3.1 JIT
???????JIT是Just In Time縮寫晚碾,稱為及時編譯技術(shù)抓半。以JVM為例,javac將源程序編譯成java字節(jié)碼格嘁,JVM通過逐條解釋將字節(jié)碼翻譯成對應(yīng)的機(jī)器指令笛求,逐條讀入,逐條解釋翻譯,執(zhí)行速度必然比c/c++編譯后的可執(zhí)行二進(jìn)制字節(jié)碼程序慢探入,為了提高執(zhí)行速度狡孔,就引入了JIT技術(shù),JIT會在運行時分析應(yīng)用程序代碼蜂嗽,識別哪些方法可以歸類為熱方法苗膝,這些方法會被JIT編譯器編譯成對應(yīng)的匯編代碼,然后存儲到代碼緩存中植旧,以后調(diào)用這些方法時就不用解釋執(zhí)行了辱揭,可以直接使用代碼緩存中已編譯好的匯編代碼,這能顯著提升應(yīng)用程序的執(zhí)行效率病附。Dalvik虛擬機(jī)在android2..2中增加了JIT问窃。
1.3.2 AOT
AOT指的是預(yù)編譯技術(shù),其全稱為Ahead Of Time完沪。AOT就是在我們安裝APK時就將dex文件直接處理成可直接供ART虛擬機(jī)使用的機(jī)器碼域庇。
1.4 APK的執(zhí)行流程
引用一張Google的圖來看一下Android對apk的執(zhí)行流程(圖片從上往下閱讀):
???????Java文件通過javac編譯成.class文件,然后通過SDK中的dx工具將.class文件轉(zhuǎn)換成Dalvik虛擬機(jī)能夠執(zhí)行的.dex文件覆积,然后與Native code(JNI)和資源文件一起打包成apk听皿,apk安裝到手機(jī)后解壓出.dex文件,Dalvik虛擬機(jī)會通過dexopt工具將.dex文件優(yōu)化技健,形成Odex文件写穴,ART則會將.dex文件通過dex2oat工具編譯得到一個ELF文件,這是一個可執(zhí)行文件雌贱。
2 虛擬機(jī)特性對比
2.1 JVM與DVM對比
-
Java虛擬機(jī)運行的是java字節(jié)碼啊送,Dalvik虛擬機(jī)運行的是Dalvik字節(jié)碼
???????java程序經(jīng)過編譯,生成java字節(jié)碼保存在.class文件中欣孤,JVM通過解碼.class文件中的內(nèi)容來運行程序馋没。而DVM運行的是Dalvik字節(jié)碼,所有的Dalvik字節(jié)碼都是由Java字節(jié)碼轉(zhuǎn)換而來降传,并打包到.dex(Dalvik Executable)可執(zhí)行文件中篷朵,DVM通過解釋.dex文件來執(zhí)行這些字節(jié)碼。
? -
Dalvik可執(zhí)行文件體積更小
???????android SDK中有個dx工具婆排,該工具負(fù)責(zé)將Java字節(jié)碼轉(zhuǎn)換為Dalvik字節(jié)碼声旺,dx工具對Java類文件重新排列,將所有Java類文件中的常量池分解段只,消除其中冗余信息腮猖,重新組合形成一個常量池,所有的類文件共享同一個常量池赞枕,使得相同的字符串澈缺、常量在DEX文件中只出現(xiàn)一次坪创,從而減少了文件的體積。 -
JVM基于棧姐赡,DVM基于寄存器
關(guān)于棧式虛擬機(jī):
- 代碼必須使用這些指令來移動變量(即push和pop)
- 代碼尺寸小和解碼效率會更高些
- 堆棧虛擬機(jī)指令有隱含的操作數(shù)莱预。
關(guān)于寄存器式虛擬機(jī):
- 使用堆棧來分配激活記錄器
- 基于寄存器代碼免去了使用push和pop命令的麻煩,減少了每個函數(shù)的指令總數(shù)项滑。
- 代碼尺寸和解碼效率不如基于棧虛擬機(jī)依沮,因為它包含操作數(shù),所以指令大于基于堆棧的指令杖们。但是基于寄存器產(chǎn)生更少的代碼悉抵,所以總的代碼數(shù)不會增加。
- 寄存器虛擬機(jī)必須從操作指令中解碼操作數(shù)摘完,需要額外的解碼操作姥饰。
因而,籠統(tǒng)說可以有以下結(jié)論:
- 要追求盡量實現(xiàn)簡單:選擇基于棧
- 傳輸代碼的大小盡量行⒅巍:選擇基于棧
- 純解釋執(zhí)行的解釋器的速度:選擇基于寄存器
- 帶有JIT編譯器的執(zhí)行引擎的速度:隨便列粪,兩者一樣;對簡易JIT編譯器而言基于棧的指令集可能反而更便于生成更快的代碼谈飒,而對比較優(yōu)化的JIT編譯器而言輸入是基于棧還是基于寄存器都無所謂岂座,經(jīng)過parse之后就變得完全一樣了。
2.2 DVM與ART對比
-
ART采用AOT技術(shù)替代了JIT
???????ART在應(yīng)用程序安裝時杭措,就已經(jīng)將所有的字節(jié)碼編譯成機(jī)器碼费什,運行的時候直接運行的是機(jī)器碼。而Dalvik則是在應(yīng)用程序運行時手素,實時地將字節(jié)碼編譯成機(jī)器碼鸳址。因此,ART與Dalvik相比泉懦,省去了運行時將字節(jié)碼編譯成機(jī)器碼的過程稿黍,極大地提升了應(yīng)用程序的運行效率。
???????雖然運行效率得到提升崩哩,但同時帶來了其它缺點:
- 安裝時需要將字節(jié)碼轉(zhuǎn)換成機(jī)器碼巡球,因此ART需要更大的存儲空間
- 安裝時需要更多的時間
提高了垃圾回收效率
???????Dalvik虛擬機(jī)在GC時,會掛起虛擬機(jī)內(nèi)部的所有線程邓嘹,然后GC查找所有可回收的對象進(jìn)行回收酣栈,回收后恢復(fù)所有掛起的線程。GC與應(yīng)用程序的運行并不是并發(fā)執(zhí)行的汹押,如果GC頻繁或者GC時間過長都會導(dǎo)致應(yīng)用程序運行卡頓矿筝。
???????ART對GC做了一定的改善,Dalvik的GC操作與應(yīng)用程序是同步執(zhí)行的(非并發(fā))鲸阻,而ART則將原來的非并發(fā)過程改成部分并發(fā)跋涣,縮短了GC時間,提升了垃圾回收效率鸟悴。提高了內(nèi)存使用率陈辱、減少了內(nèi)存碎片化
???????Dalvik虛擬機(jī)垃圾回收采用了Mark and Sweep算法,即“標(biāo)記-清除”算法细诸,這種算法先對需要回收的內(nèi)存區(qū)域進(jìn)行標(biāo)記沛贪,然后再統(tǒng)一清除,它是一種比較高效的算法震贵,但是帶來的弊端是會造成可用內(nèi)存塊的不連續(xù)利赋,碎片化嚴(yán)重。虛擬機(jī)多次gc之后猩系,本來連續(xù)的內(nèi)存區(qū)域變得千瘡百孔媚送,以后為對象分配內(nèi)存尋址會越來越難。
???????而ART在內(nèi)存分配上做了優(yōu)化寇甸,比如它開辟了一塊名為Large Object Space的內(nèi)存區(qū)域塘偎,專門用來存放大對象,同時還引入了一個名為moving collector的技術(shù)拿霉,專門用來將gc后不連續(xù)的物理內(nèi)存塊對齊吟秩,解決了Dalvik上內(nèi)存碎片化嚴(yán)重的問題。
參考文章
https://blog.csdn.net/qq_27688259/article/details/82252855
http://www.reibang.com/p/5c00dd2bece6
http://www.reibang.com/p/1f779586efdc
https://blog.csdn.net/k1457047898/article/details/53471951