首先,讓我們來思考下面幾個問題:
什么是Dalvik虛擬機?
Dalvik VM與JVM有什么區(qū)別?
Dalvik VM有什么新的特點?
Dalvik VM的架構(gòu)是怎么樣的?
首先,我得承認第一個問題問得很傻:什么是Dalvik虛擬機?沒有人給出過一個明確的定義,但是,我們似乎可以從人們對Java虛擬機的描述中得到些信息。
Java虛擬機(JVM)是一個虛構(gòu)出來的計算機,是通過在實際的計算機上仿真模擬各種計算機功能來實現(xiàn)的。它有自己完善的硬件架構(gòu)(如處理器、堆棧、寄存器等),還具有相應(yīng)的指令系統(tǒng)。使用“Java虛擬機”程序就是為了支持與操作系統(tǒng)無關(guān)、在任何系統(tǒng)中都可以運行的程序。
因此,我們不妨對Dalvik虛擬機作出這樣的描述:
Dalvik虛擬機是Android程序的虛擬機,是Android中Java程序的運行基礎(chǔ)。其指令集基于寄存器架構(gòu),執(zhí)行其特有的文件格式——dex字節(jié)碼來完成對象生命周期管理、堆棧管理、線程管理、安全異常管理、垃圾回收等重要功能。它的核心內(nèi)容是實現(xiàn)庫(libdvm.so),大體由C語言實現(xiàn)。依賴于Linux內(nèi)核的一部分功能——線程機制、內(nèi)存管理機制,能高效使用內(nèi)存,并在低速CPU上表現(xiàn)出的高性能。每一個Android應(yīng)用在底層都會對應(yīng)一個獨立的Dalvik虛擬機實例,其代碼在虛擬機的解釋下得以執(zhí)行。
與Dalvik虛擬機關(guān)系最密切的非JVM莫屬,在Android源碼readme文檔中有這樣一段話:Much of the code under this directory originally came from the Apache Harmony project, and as such contains the standard Apache header comment. Some of the code was written originally for the Android project…
Dalvik VM與Apache Harmony 項目關(guān)系源遠流長,因此,與JVM關(guān)系自然就密切了。
然而:Dalvik VM ≠Java VM
dalvik基于寄存器,而JVM基于stack
Dalvik執(zhí)行的是特有的DEX文件格式,而JVM運行的是*.class文件格式。
優(yōu)勢:1、在編譯時提前優(yōu)化代碼而不是等到運行時
2、 虛擬機很小,使用的空間也小;被設(shè)計來滿足可高效運行多種虛擬機實例。
3、常量池已被修改為只使用32位的索引,以 簡化解釋器
JVM的字節(jié)碼主要是零地址形式的,概念上說JVM是基于棧的架構(gòu)。Google Android平臺上的應(yīng)用程序的主要開發(fā)語言是Java,通過其中的Dalvik VM來運行Java程序。為了能正確實現(xiàn)語義,Dalvik VM的許多設(shè)計都考慮到與JVM的兼容性;但它卻采用了基于寄存器的架構(gòu),其字節(jié)碼主要是二地址/三地址的混合形式。
基于棧與基于寄存器的架構(gòu),誰更快?現(xiàn)在實際的處理器,大多都是基于寄存器的架構(gòu),從側(cè)面反映出基于寄存器比基于棧的架構(gòu)更與實際的處理器接近。但對于VM來說,源架構(gòu)的求值?;蛘呒拇嫫鞫伎赡苁怯脤嶋H機器的內(nèi)存來模擬的,所以性能特性與實際硬件又有不同。一般認為基于寄存器架構(gòu)的Dalvik VM比基于棧架構(gòu)JVM執(zhí)行效率更高,原因是:雖然零地址指令更緊湊,但完成操作需要更多的load/store指令,也意味著更多的指令分派(instruction dispatch)次數(shù)與內(nèi)存訪問次數(shù);訪問內(nèi)存是執(zhí)行速度的一個重要瓶頸,二地址或三地址指令雖然每條指令占的空間較多,但總體來說可以用更少的指令完成操作,指令分派與內(nèi)存訪問次數(shù)都較少。
我們從下面的截圖可以明了的看到與同一段Java代碼對應(yīng)的Java bytecode 與Dalvid bytecode的比較。
專有的DEX文件格式
一個應(yīng)用中會定義很多類,
編譯完成后即會有很多相應(yīng)
的CLASS文件,CLASS文件
間會有不少冗余的信息。
dex字節(jié)碼和標準Java的字節(jié)碼(Class)在結(jié)構(gòu)上的一個區(qū)別是dex字節(jié)碼將多個文件整合成一個,這樣,除了減少整體的文件尺寸,I/O操作,也提高了類的查找速度。
原來每個類文件中的常量池現(xiàn)在由DEX文件中一個常量池來管理。
DEX文件可以進行進一步優(yōu)化。優(yōu)化主要是針對以下幾個方面:
1、調(diào)整所有字段的字節(jié)序(LITTLE_ENDIAN)和對齊結(jié)構(gòu)中的沒一個域
2、驗證DEX文件中的所有類
3、對一些特定的類進行優(yōu)化,對方法里的操作碼進行優(yōu)化
優(yōu)化 優(yōu)化后的文件大小會有所增加,應(yīng)該是原DEX文件的1-4倍。
odex是為了在運行過程中進一步提高性能,對dex文件的進一步優(yōu)化
一個應(yīng)用,一個虛擬機實例,一個進程?。。?/p>
每一個Android應(yīng)用都運行在一個Dalvik虛擬機實例里,而每一個虛擬機實例都是一個獨立的進程空間。每個進程之間可以通信(IPC,Binder機制實現(xiàn))。虛擬機的線程機制,內(nèi)存分配和管理,Mutex等等都是依賴底層操作系統(tǒng)而實現(xiàn)的。
不同的應(yīng)用在不同的進程空間里運行,當一個虛擬機關(guān)閉或意外中止時不會對其它 虛擬機造成影響,可以最大程度的保護應(yīng)用的安全和獨立運行。
Zygote是虛擬機實例的孵化器。AndroidRuntime.cpp中ZygoteInit.main()的執(zhí)行會完成一個分裂,分裂出來的子進程繼續(xù)初始化Java層的架構(gòu),這個分裂出來的進程就是system_server。每當系統(tǒng)要求執(zhí)行一個Android應(yīng)用程序,Zygote就會FORK出一個子進程來執(zhí)行該應(yīng)用程序。這樣做的好處顯而易見:Zygote進程是在系統(tǒng)啟動時產(chǎn)生的,它會完成虛擬機的初始化,庫的加載,預(yù)置類庫的加載和初始化等等操作,而在系統(tǒng)需要一個新的虛擬機實例時,Zygote通過復(fù)制自身,最快速的提供個系統(tǒng)。另外,對于一些只讀的系統(tǒng)庫,所有虛擬機實例都和Zygote共享一塊內(nèi)存區(qū)域,大大節(jié)省了內(nèi)存開銷。
聯(lián)系客服