JVM驹闰、DVM瘪菌、ART的區(qū)別
Android底層學(xué)習(xí)必須要了解一下java的虛擬機(jī)JVM,以及Android的虛擬機(jī)DVM(Dalvik VM) 以及ART嘹朗。
實(shí)際上Android的DVM以及ART都不是JVM的一種师妙,因?yàn)樗鼈儧]有遵從JVM的規(guī)范。
廢話不多說屹培,先分析一下JVM
JVM
JVM是整個(gè)java平臺(tái)的基石默穴,是java語言編譯代碼的運(yùn)行平臺(tái)怔檩。
我們先來看看JVM的結(jié)構(gòu)(面試必問:JVM內(nèi)存模型)
可以看出JVM結(jié)構(gòu)包含運(yùn)行時(shí)數(shù)據(jù)區(qū),執(zhí)行引擎蓄诽,本地方法庫薛训,本地方法接口組成。其中類加載子系統(tǒng)并不屬于JVM虛擬機(jī)的內(nèi)部結(jié)構(gòu)仑氛。
1.類的生命周期
Java文件被編譯后生成Class文件乙埃,這種二進(jìn)制格式文件不依賴于特定硬件和操作系統(tǒng)。每一個(gè)Class文件都對(duì)應(yīng)著唯一的類或者接口定義信息锯岖。無論任何語言只要能編譯成Class文件介袜,都能被Java虛擬機(jī)識(shí)別并執(zhí)行。
一個(gè)Java文件被加載到Java虛擬機(jī)內(nèi)存中到從內(nèi)存中卸載的過程被稱為類的生命周期出吹。類的生命周期包括:加載遇伞、鏈接、初始化捶牢、使用鸠珠、卸載,其中鏈接包括了三個(gè)階段:驗(yàn)證叫确,準(zhǔn)備跳芳,解析。因此類的生命周期包括了7個(gè)階段竹勉。
接下來大致介紹一下各個(gè)階段的工作:
1)加載:查找并加載Class文件飞盆。
2)鏈接:包括驗(yàn)證、準(zhǔn)備次乓、和解析吓歇。
驗(yàn)證:確保被導(dǎo)入類型的正確性
準(zhǔn)備:為類的靜態(tài)字段分配字段,并使用默認(rèn)值初始化這個(gè)字段
解析:虛擬機(jī)將常量池內(nèi)的符號(hào)引用替換為直接引用
3)初始化:將類變量初始化為正確的初始值
其他的就是使用和卸載票腰,不必多說城看。
2.運(yùn)行時(shí)數(shù)據(jù)區(qū)域
也就是面試常問的JVM內(nèi)存模型,主要分為程序計(jì)數(shù)器杏慰,棧测柠,堆,方法區(qū)和本地方法區(qū)缘滥。
1)程序計(jì)數(shù)器:
為保證程序能夠連續(xù)的執(zhí)行下去轰胁,處理器必須具有某些手段來確定下一條指令的地址。程序計(jì)數(shù)器就起到了這個(gè)作用朝扼。程序計(jì)數(shù)器(Program Counter Register)也叫作PC寄存器赃阀,是一塊較小的內(nèi)存空間。在虛擬機(jī)概念模型中擎颖,字節(jié)碼解釋器的工作就是通過改變程序計(jì)數(shù)器來選取下一條需要執(zhí)行的字節(jié)碼指令榛斯。Java虛擬機(jī)的多線程是通過輪流切換并分配處理器執(zhí)行時(shí)間的方式來實(shí)現(xiàn)的观游,在一個(gè)確定的時(shí)刻只有一個(gè)處理器執(zhí)行一條線程中的指令,為了線程在切換后能回復(fù)到正確的執(zhí)行為止驮俗,每個(gè)線程都會(huì)有一個(gè)獨(dú)立的程序計(jì)數(shù)器懂缕。因此,程序計(jì)數(shù)器是線程私有的王凑。
程序計(jì)數(shù)器是Java虛擬機(jī)規(guī)范中唯一沒有規(guī)定OutOfMemoryError情況的數(shù)據(jù)區(qū)域提佣。
2)Java虛擬機(jī)棧:
每一條Java虛擬機(jī)線程都有一個(gè)線程私有的Java虛擬機(jī)棧(Java Virtual Machine Stacks)。它的生命周期與線程相同荤崇。Java虛擬機(jī)棧儲(chǔ)存線程中的Java方法調(diào)用的狀態(tài),包括局部變量潮针、參數(shù)术荤、返回值以及運(yùn)算的中間結(jié)果。一個(gè)Java虛擬機(jī)棧包括多個(gè)棧幀每篷,一個(gè)棧幀用來存儲(chǔ)局部變量表瓣戚、操作數(shù)棧、動(dòng)態(tài)鏈接焦读、方法出口等信息子库。當(dāng)線程調(diào)用一個(gè)Java方法的時(shí)候,虛擬機(jī)壓入一個(gè)新的棧幀到該線程的Java虛擬機(jī)棧中矗晃,當(dāng)該方法執(zhí)行完成后仑嗅,這個(gè)棧幀就從java虛擬機(jī)棧中彈出。
Java虛擬機(jī)棧規(guī)定了兩種異常情況
1:如果線程請(qǐng)求分配的棧容量超過Java虛擬機(jī)所允許的最大容量张症,會(huì)拋出StackOverflowError仓技。
2:如果Java虛擬機(jī)棧可以動(dòng)態(tài)擴(kuò)展俗他,但是無法申請(qǐng)到足夠的內(nèi)存脖捻,或者在創(chuàng)建新的線程時(shí)沒有足夠的內(nèi)存去創(chuàng)建對(duì)應(yīng)的Java虛擬機(jī)棧,則會(huì)拋出OutOfMemoryError兆衅。
3)本地方法棧
Java虛擬機(jī)實(shí)現(xiàn)可能需要C Stacks來支持Native語言地沮,這個(gè)C Stacks就是本地方法棧(Native Method Stack)。與Java虛擬機(jī)棧累死羡亩,只不過本地方法棧是用來支持Native方法的摩疑。
4)Java堆
Java堆(Java Heap)是被所有線程共享的運(yùn)行時(shí)內(nèi)存區(qū)域。Java堆用來存放對(duì)象實(shí)例夕春,幾乎所有的對(duì)象實(shí)例都會(huì)在這里分配內(nèi)存未荒。Java堆存儲(chǔ)的對(duì)象被垃圾收集器管理,這些受管理的對(duì)象無法顯式的銷毀及志。
5)方法區(qū)
方法區(qū)(Method Area)是被所有線程共享的運(yùn)行時(shí)內(nèi)存區(qū)域片排。用來存儲(chǔ)已經(jīng)被Java虛擬機(jī)加載的類的結(jié)構(gòu)信息寨腔,包括運(yùn)行時(shí)常量池、字段率寡、方法信息迫卢、靜態(tài)變量等數(shù)據(jù)。方法區(qū)是Java堆的邏輯組成部分冶共,它一樣在物理上不需要連續(xù)乾蛤,并且可以選擇在方法區(qū)中不實(shí)現(xiàn)垃圾收集。
Dalvik虛擬機(jī)
Dalvik虛擬機(jī)(Dalvik Virtual Machine)捅僵,簡(jiǎn)稱Dalvik VM或者DVM家卖。
為什么開篇說DVM不屬于JVM的范疇,下面給出答案庙楚。
DVM與JVM的區(qū)別
1)基于的架構(gòu)不同
JVM基于棧上荡,意味著需要去棧中讀寫數(shù)據(jù),所需要的指令會(huì)更多馒闷,這樣會(huì)導(dǎo)致速度變慢酪捡,對(duì)于性能有限的移動(dòng)設(shè)備顯然不合適。DVM是基于寄存器的纳账,它沒有基于棧的虛擬機(jī)在復(fù)制數(shù)據(jù)時(shí)而使用大量的出入棧指令逛薇,同事指令更緊湊、簡(jiǎn)潔疏虫。但是由于顯式的制定了操作數(shù)永罚,所以基于寄存器的指令會(huì)比基于棧的指令要大。
2)執(zhí)行字節(jié)碼不同
JVM中卧秘,java類被編譯成一個(gè)或多個(gè).class文件尤蛮,并打包成.jar文件,而后JVM會(huì)通過相應(yīng)的.class文件和.jar文件獲取相應(yīng)的字節(jié)碼斯议。
而DVM會(huì)用dx工具把所有的class文件打包成一個(gè).dex文件产捞,然后DVM會(huì)從該.dex文件中讀取指令和數(shù)據(jù)。這個(gè).dex文件將所有的.class文件里面所包含的信息全部整合到了一起哼御,這樣加載就加快了速度坯临。
3)DVM允許在有限的內(nèi)存中同時(shí)運(yùn)行多個(gè)進(jìn)程
DVM經(jīng)過優(yōu)化,允許在有限的內(nèi)存中同時(shí)運(yùn)行多個(gè)進(jìn)程恋昼。在Android中每一個(gè)應(yīng)用都運(yùn)行在一個(gè)DVM實(shí)例中看靠,每一個(gè)DVM實(shí)例都運(yùn)行在一個(gè)獨(dú)立的進(jìn)程空間,獨(dú)立的進(jìn)程可以防止虛擬機(jī)崩潰時(shí)所有程序都被關(guān)閉液肌。
4)DVM由Zygote創(chuàng)建并初始化
在《Android系統(tǒng)啟動(dòng)流程》中提到過挟炬,Zygote是一個(gè)DVM進(jìn)程,同時(shí)也用來創(chuàng)建和初始化其他DVM進(jìn)程。每當(dāng)系統(tǒng)需要一個(gè)應(yīng)用程序進(jìn)程的時(shí)候谤祖,Zygote就會(huì)fork自身婿滓,快速地創(chuàng)建和初始化一個(gè)DVM實(shí)例,用于程序運(yùn)行粥喜。對(duì)于一些只讀的系統(tǒng)庫凸主,所有的DVM實(shí)例都會(huì)和Zygote共享一塊內(nèi)存區(qū)域,節(jié)省內(nèi)存開銷额湘。
5)DVM有共享機(jī)制
DVM擁有預(yù)加載-共享機(jī)制卿吐,不同應(yīng)用之間運(yùn)行時(shí)可以共享相同的類,擁有更高的效率锋华。而JVM機(jī)制不存在這種共享機(jī)制嗡官。不同的程序,打包以后程序都是彼此獨(dú)立的毯焕,即便是他們使用了相同的類谨湘,運(yùn)行時(shí)也都是單獨(dú)加載和運(yùn)行的。
6)DVM早期沒有JIT編譯器
JVM使用了JIT(Just In Time Compiler)芥丧,而DVM早期沒有使用JIT編譯器。早期DVM執(zhí)行代碼坊罢,都需要解釋器將dex代碼編譯成機(jī)器碼续担,然后交給系統(tǒng)處理,效率不是很高活孩。Android 2.2之后開始為DVM使用了JIT編譯器物遇,它會(huì)對(duì)多次運(yùn)行的代碼(熱點(diǎn)代碼)進(jìn)行編譯,生成相當(dāng)精簡(jiǎn)的本地機(jī)器碼(Native Code)憾儒,這樣在下次執(zhí)行到相同的邏輯時(shí)询兴,直接使用編譯好的機(jī)器碼即可。需要注意的是起趾,應(yīng)用程序每次重新運(yùn)行的時(shí)候诗舰,都需要重做這個(gè)編譯工作。
ART虛擬機(jī)
ART(Android Runtime)虛擬機(jī)是Android 4.4發(fā)布的训裆,用來替換Dalvik虛擬機(jī)眶根。Android 4.4默認(rèn)還是DVM,但是可以在開發(fā)者選項(xiàng)中切換成ART边琉。在Android 5.0之后默認(rèn)采用了ART属百,從此DVM退出了歷史舞臺(tái)。
ART與DVM的區(qū)別
1)前文了解到变姨,DVM中的應(yīng)用每次運(yùn)行時(shí)族扰,字節(jié)碼都需要通過JIT編譯器編譯為機(jī)器碼,這樣會(huì)使應(yīng)用程序的運(yùn)行效率降低。而在ART中渔呵,系統(tǒng)安裝應(yīng)用程序時(shí)會(huì)進(jìn)行一次AOT(ahead of time compilation)怒竿,將字節(jié)碼預(yù)編譯成機(jī)器碼并存儲(chǔ)在本地,這樣應(yīng)用程序每次運(yùn)行時(shí)就不需要執(zhí)行編譯了厘肮,會(huì)大大增加效率愧口。但是AOT不是完美的,它的缺點(diǎn)主要有兩個(gè):第一個(gè)是AOT會(huì)使安裝應(yīng)用的時(shí)間變長(zhǎng)类茂,尤其是復(fù)雜的應(yīng)用耍属。第二個(gè)是字節(jié)碼預(yù)先編譯成機(jī)器碼,機(jī)器碼需要存儲(chǔ)空間會(huì)多一些巩检。為了解決這兩個(gè)問題厚骗,Android 7.0版本中的ART加入了JIT即時(shí)編譯器,作為AOT的一個(gè)補(bǔ)充兢哭。應(yīng)用程序安裝時(shí)并不會(huì)將字節(jié)碼全部編譯成機(jī)器碼领舰,而是在系統(tǒng)運(yùn)行中將熱點(diǎn)代碼編譯成機(jī)器碼,從而縮短應(yīng)用程序安裝時(shí)間迟螺,并且節(jié)省內(nèi)存冲秽。
2)DVM是為32位CPU設(shè)計(jì)的,而ART是支持64位并且兼容32位CPU矩父,這也是DVM被淘汰的主要原因之一锉桑。
3)ART對(duì)垃圾回收機(jī)制進(jìn)行了改進(jìn),比如更頻繁的執(zhí)行并行垃圾收集窍株,將GC暫停由2次減少為1次等等民轴。
4)ART運(yùn)行時(shí)堆空間劃分和DVM不同。
下面主要講一下ART對(duì)垃圾回收機(jī)制的改進(jìn):
ART垃圾回收
DVM的垃圾回收算法采用的是標(biāo)記-清除算法(Mark-Sweep)球订,ART改進(jìn)了該算法后裸,并且使用了多種垃圾收集器。
1.Concurrent Mark Sweep(CMS):CMS收集器是一種獲取最短收集暫停時(shí)間為目標(biāo)的收集器冒滩,采用了標(biāo)記-清除算法實(shí)現(xiàn)微驶。它是完整的堆垃圾收集器。
2.Concurrent Partial Mark Sweep:部分完整的堆垃圾收集器
3.Concurrent Sticky Mark Sweep:粘性收集器开睡,基于分代垃圾收集思想祈搜,它只能釋放上次GC以來分配的對(duì)象。這個(gè)垃圾收集器比一個(gè)完整或者部分完整的垃圾收集器掃描的更加頻繁士八,因?yàn)樗於視和r(shí)間更短容燕。
4.Marksweep + Semispace:肺病發(fā)的GC,復(fù)制GC用于堆轉(zhuǎn)換以及齊性空間壓縮(碎片整理)婚度。
總結(jié)
DVM和ART知識(shí)體系完全可以寫一本書蘸秘,如果想要更多的了解它請(qǐng)閱讀專業(yè)的書籍和博客官卡,比如老羅的博客。