Android 知識(shí):JVM耘成、DVM、ART的區(qū)別

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)存模型)

image

可以看出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è)的書籍和博客官卡,比如老羅的博客。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末醋虏,一起剝皮案震驚了整個(gè)濱河市寻咒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌颈嚼,老刑警劉巖毛秘,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異阻课,居然都是意外死亡叫挟,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門限煞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抹恳,“玉大人,你說我怎么就攤上這事署驻》芟祝” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵旺上,是天一觀的道長(zhǎng)瓶蚂。 經(jīng)常有香客問我,道長(zhǎng)宣吱,這世上最難降的妖魔是什么窃这? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮凌节,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘洒试。我一直安慰自己倍奢,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布垒棋。 她就那樣靜靜地躺著卒煞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪叼架。 梳的紋絲不亂的頭發(fā)上畔裕,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音乖订,去河邊找鬼扮饶。 笑死,一個(gè)胖子當(dāng)著我的面吹牛乍构,可吹牛的內(nèi)容都是我干的甜无。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼岂丘!你這毒婦竟也來了陵究?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤奥帘,失蹤者是張志新(化名)和其女友劉穎铜邮,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體寨蹋,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡松蒜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了钥庇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片牍鞠。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖评姨,靈堂內(nèi)的尸體忽然破棺而出难述,到底是詐尸還是另有隱情,我是刑警寧澤吐句,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布胁后,位于F島的核電站,受9級(jí)特大地震影響嗦枢,放射性物質(zhì)發(fā)生泄漏攀芯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一文虏、第九天 我趴在偏房一處隱蔽的房頂上張望侣诺。 院中可真熱鬧,春花似錦氧秘、人聲如沸年鸳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽搔确。三九已至,卻和暖如春灭忠,著一層夾襖步出監(jiān)牢的瞬間膳算,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來泰國(guó)打工弛作, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留涕蜂,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓映琳,卻偏偏與公主長(zhǎng)得像宇葱,于是被迫代替她去往敵國(guó)和親瘦真。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容