這篇文章內容大部分來自一年前的一篇調研報告,加上對dalvik虛擬機的一些認識,匆忙整理出來供大家參考。如有不對的地方請不吝指出。
I.什麼是Dalvik虛擬機?
II.DalvikVM與JVM有什麼區別?
III.DalvikVM有什麼新的特點?
IV.DalvikVM的架構是怎麼樣的?
n?111111111111111111
什麼是Dalvik虛擬機?沒有人給出過一個明確的定義,但是,我們似乎可以從人們對Java虛擬機的描述中得到些信息。
Java虛擬機(JVM)是一個虛構出來的計算機,是通過在實際的計算機上仿真模擬各種計算機功能來實現的。它有自己完善的硬件架構(如處理器、堆棧、寄存器等),還具有相應的指令系統。使用“Java虛擬機”程序就是為了支持與操作系統無關、在任何系統中都可以運行的程序。
因此,我們不妨對Dalvik虛擬機作出這樣的描述:
Dalvik虛擬機是Android程序的虛擬機,是Android中Java程序的運行基礎。其指令集基於寄存器架構,執行其特有的文件格式——dex字節碼來完成對象生命周期管理、堆棧管理、線程管理、安全異常管理、垃圾回收等重要功能。它的核心內容是實現庫(libdvm.so),架構由C語言實現。依賴於Linux內核的一部分功能——線程機制、內存管理機制,能高效使用內存,並在低速CPU上表現出的高性能。每一個Android應用在底層都會對應一個獨立的Dalvik虛擬機實例,其代碼在虛擬機的解釋下得以執行。
n?2222222222222222222222222222222222
然而:DalvikVM ≠Java VMI.dalvik基於寄存器,而JVM基於stack II.Dalvik執行的是特有的DEX文件格式,而JVM運行的是*.class文件格式。
優勢:1、在編譯時提前優化代碼而不是等到運行時
2、虛擬機很小,使用的空間也小;被設計來 滿足可高效運行多種虛擬機實例。
3、常量池已被修改為只使用32位的索引,以簡化解釋器
JVM的字節碼主要是零地址形式的,概念上說JVM是基於棧的架構。Google Android���台上的應用程序的主要開發語言是Java,通過其中的DalvikVM來運行Java程序。為了能正確實現語義,DalvikVM的許多設計都考慮到與JVM的兼容性;但它卻采用了基於寄存器(見補充1)的架構,其字節碼主要是二地址/三地址的混合形式。
基於棧與基於寄存器的架構,誰更快?現在實際的處理器,大多都是基於寄存器的架構,從側面反映出基於寄存器比基於棧的架構更與實際的處理器接近。但對於VM來說,源架構的求值棧或者寄存器都可能是用實際機器的內存來模擬的,所以性能特性與實際硬件又有不同。一般認為基於寄存器架構的DalvikVM比基於棧架構JVM執行效率更高,原因是:雖然零地址指令更緊湊,但完成操作需要更多的load/store指令,也意味著更多的指令分派(instruction dispatch)次數與內存訪問次數;訪問內存是執行速度的一個重要瓶頸,二地址或三地址指令雖然每條指令占的空間較多,但總體來說可以用更少的指令完成操作,指令分派與內存訪問次數都較少。
我們從下面的截圖可以明了的看到與同一段Java代碼對應的Java bytecode 與Dalvid bytecode的比較。(摘自網絡)
??
n33333333333333333333333333333333333
專有的DEX文件格式
一個應用中會定義很多類,
編譯完成後即會有很多相應
的CLASS文件,CLASS文件
間會有不少冗余的信息。
udex字節碼和標准Java的字節碼(Class)在結構上的一個區別是dex字節碼將多個文件整合成一個,這樣,除了減少整體的文件尺寸,I/O操作,也提高了類的查找速度。
u原來每個類文件中的常量池現在由DEX文件中一個常量池來管理。
uDEX文件可以進行進一步優化。優化主要是針對以下幾個方面:
1、調整所有字段的字節序(LITTLE_ENDIAN)和對齊結構中的沒一個域
2、驗證DEX文件中的所有類
3、對一些特定的類進行優化,對方法裡的操作碼進行優化,優化優化後的文件大小會有所增加,應該是原DEX文件的1-4倍。odex是為了在運行過程中進一步提高性能,對dex文件的進一步優化, 這個步驟在安裝程序的時候可以看到。
DEX文件的生成:
Android系統和Dalvik虛擬機提供了工具(DX) 在把Java源代碼編譯成CLASS文件後 使用DX工具(見補充2) DEX文件的結構相對於.jar更加緊湊 但是為了獲得高效率我們還得進一步對.dex進行優化。
n444444444444444444444444444
一個應用,一個虛擬機實例,一個進程!!!
u每一個Android應用都運行在一個Dalvik虛擬機實例裡,而每一個虛擬機實例都是一個獨立的進程空間。每個進程之間可以通信(IPC,Binder機制實現)。虛擬機的線程機制,內存分配和管理,Mutex等等都是依賴底層操作系統而實現的。u 不同的應用在不同的進程空間裡運行,當一個虛擬機關閉或意外中止時不會對其它虛擬機造成影響,可以最大程度的保護應用的安全和獨立運行。
u Zygote是虛擬機實例的孵化器。AndroidRuntime.cpp中ZygoteInit.main()的執行會完成一個分裂,分裂出來的子進程繼續初始化Java層的架構,這個分裂出來的進程就是system_server。每當系統要求執行一個Android應用程序,Zygote就會FORK出一個子進程來執行該應用程序。這樣做的好處顯而易見:Zygote進程是在系統啟動時產生的,它會完成虛擬機的初始化,庫的加載,預置類庫的加載和初始化等等操作,而在系統需要一個新的虛擬機實例時,Zygote通過復制自身,最快速的提供個系統。另外,對於一些只讀的系統庫,所有虛擬機實例都和Zygote共享一塊內存區域,大大節省了內存開銷。(下圖借簽網絡資源)