《Dalvik虛擬機簡介及架構(gòu)級移植優(yōu)化方向》由會員分享,可在線閱讀,更多相關(guān)《Dalvik虛擬機簡介及架構(gòu)級移植優(yōu)化方向(20頁珍藏版)》請在裝配圖網(wǎng)上搜索。
1、LOGOAndroid Dalvik 虛擬機初識及架構(gòu)簡析LOGO嵌入式系統(tǒng)概述嵌入式系統(tǒng)概述 Dalvik虛擬機與Java虛擬機的區(qū)別 Dalvik虛擬機源碼目錄簡析 Dalvik虛擬機專有工具的功能及使用 Dalvik虛擬機初識及基本特性1234本本節(jié)節(jié)主主要要內(nèi)內(nèi)容容 Dalvik虛擬機核心執(zhí)行引擎5 Dalvik虛擬機的移植及優(yōu)化方向LOGO1、Dalvik虛擬機初識及基本特性什么是Dalvik虛擬機?讓我們從認識Java虛擬機開始:Java虛擬機(JVM)是一個虛構(gòu)出來的計算機,是通過在實際的計算機上仿真模擬各種計算機功能來實現(xiàn)的。它有自己完善的硬件架構(gòu)(如處理器、堆棧、寄存器等),
2、還具有相應(yīng)的指令系統(tǒng)。使用“Java虛擬機”程序就是為了支持與操作系統(tǒng)無關(guān)、在任何系統(tǒng)中都可以運行的程序。Davlik虛擬機同Java虛擬機同樣是運行Java程序的虛擬機,但Davlik虛擬機具有其獨特特性:Dalvik虛擬機是Android程序的虛擬機,是Android中Java程序的運行基礎(chǔ)。其指令集基于寄存器基于寄存器架構(gòu),執(zhí)行其特有的文件格式特有的文件格式dex字節(jié)碼來完成對象生命周期管理、堆棧管理、線程管理、安全異常管理、垃圾回收等重要功能。它的核心內(nèi)容是實現(xiàn)庫(libdvm.so),架構(gòu)由C語言實現(xiàn)。依賴于Linux內(nèi)核的一部分功能線程機制、內(nèi)存管理機制,能高效使用內(nèi)存,并在低速C
3、PU上表現(xiàn)出的高性能。每一個Android應(yīng)用在底層都會對應(yīng)一個獨立的Dalvik虛擬機實例,其代碼在虛擬機的解釋下得以執(zhí)行。讓我們看看Dalvik虛擬機處在Android系統(tǒng)架構(gòu)的什么位置:LOGOLOGO2、 Dalvik虛擬機與Java虛擬機的區(qū)別 然而:Dalvik VM Java VMI.dalvik基于寄存器,而JVM基于stack II.Dalvik執(zhí)行的是特有的DEX文件格式,而JVM運行的是*.class文件格式。優(yōu)勢:1、在編譯時提前優(yōu)化代碼而不是等到運行時2、 虛擬機很小,使用的空間也?。槐辉O(shè)計來滿足可高效運行多種虛擬機實例。3、常量池已被修改為只使用32位的索引,以簡化
4、解釋器LOGOJVM的字節(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)存來模擬的,所以性能特性與實際硬件又有不同。一般認為基于寄存器
5、架構(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的比較。LOGOLOGODalvik字節(jié)碼以16位為單元(或許叫“雙字節(jié)碼”更準(zhǔn)確 )。上面代碼中有5條指令,其中mul
6、-int/lit8指令占2單元,其余每條都只占1單元,共6單元=12字節(jié)。Java字節(jié)碼以1字節(jié)為單元。上面代碼中有11條指令,每條都只占1單元,共11單元=11字節(jié)。 基于寄存器與基于棧的區(qū)別更詳細的介紹見補充文檔?;诩拇嫫髋c基于棧的區(qū)別更詳細的介紹見補充文檔。LOGODalvik專有的專有的DEX文件格式文件格式一個應(yīng)用中會定義很多類,編譯完成后即會有很多相應(yīng)的CLASS文件,CLASS文件間會有不少冗余的信息。dex字節(jié)碼和標(biāo)準(zhǔn)Java的字節(jié)碼(Class)在結(jié)構(gòu)上的一個區(qū)別是dex字節(jié)碼將多個文件整合成一個,這樣,除了減少整體的文件尺寸,I/O操作,也提高了類的查找速度。原來每個類文
7、件中的常量池現(xiàn)在由DEX文件中一個常量池來管理。DEX文件可以進行進一步優(yōu)化。優(yōu)化主要是針對以下幾個方面: 1、調(diào)整所有字段的字節(jié)序(LITTLE_ENDIAN)和對齊結(jié)構(gòu)中的沒一個域 2、驗證DEX文件中的所有類 3、對一些特定的類進行優(yōu)化,對方法里的操作碼進行優(yōu)化 DEX字節(jié)碼的生成過程將在后續(xù)的專有工具介紹中給出。字節(jié)碼的生成過程將在后續(xù)的專有工具介紹中給出。為什么棄用已有的字節(jié)碼文件(CLASS文件)而采用新的格式呢?LOGO3、 Dalvik虛擬機源碼目錄簡析通過以上的介紹,我們對Dalvik VM能實現(xiàn)的功能以及為什么需要這么一個虛擬機有了初步的認識。觀其內(nèi)部,Android VM
8、的架構(gòu)是什么樣子的呢?在源碼中,Dalvik VM相關(guān)的內(nèi)容在Android中是一個獨立的代碼路徑:dalvik/,其中包含了目標(biāo)機和主機的內(nèi)容。其主要的目錄如下所示:Dalvik/|-Dx|-Vm| |-Arch| -Mterp| -Native| -Compiler|-DalvikvmDalvik/dx目錄的內(nèi)容是dx工具庫,其最終將dx專有工具(可執(zhí)行文件)。另外與dx目錄同級的文件夾dexdump、tools同樣對應(yīng)幾個專有工具。Dalvik/vm目錄的內(nèi)容是虛擬機核心實現(xiàn),其最終將生成libdvm.so(Dalvik虛擬機)。Davlik /dalvikvm目錄中的內(nèi)容是虛擬機的入口
9、程序,會生成dalvilvm可執(zhí)行程序。LOGO由于Dalvik中許多代碼直接來源于Apache Harmony項目,因此,通過了解Apache Harmony項目對我們認識DalvikVM有很大的幫助。Apache Harmony技術(shù)架構(gòu)如下所示:LOGO從應(yīng)用程序的執(zhí)行流程來看Dalvik VM的組成部分:DX工具:由Java編譯器編譯后的.class轉(zhuǎn)換成DE格式。類加裁器:1、原始加載器,加載native實現(xiàn)的類;2、加載器object,加載java實現(xiàn)的類。(所有process共享)執(zhí)行引擎(解釋器):根據(jù)其自身的一套指令集對dalvik bytecode進行解釋。另外包括在此流程中
10、實現(xiàn)的內(nèi)存管理及線程機制LOGODEX文件的生成:Android系統(tǒng)和Dalvik虛擬機提供了工具(DX) 在把Java源代碼編譯成CLASS文件后 使用DX工具 DEX文件的結(jié)構(gòu)相對于.jar更加緊湊 但是為了獲得高效率我們還得進一步對.dex進行優(yōu)化。LOGO4、Dalvik虛擬機專有工具的功能及使用Dalvik的虛擬機專有工具的功能其實很簡單:改造并優(yōu)化java字節(jié)碼。一般來說,啟動一個Dalvik虛擬機需要啟動一個Android應(yīng)用程序來完成,其實我們可以直接使用Dalvik虛擬機:dx工具可以單獨剝離出來使用。如,我們在pc上用java編譯器把java源碼編譯成class字節(jié)碼(這個
11、步驟也可以在Linux服務(wù)器上完成),然后在linux上直接使用dx把該class字節(jié)碼變成dex字節(jié)碼(可以通過dx直接生成打包好的DEX格式的文件,如.jar等),如下有一個簡單 例子:% echo class Foo public static void main(String args) System.out.println(Hello, world); Foo.java% javac Foo.java% dx -dex -output=foo.jar Foo.class% adb push foo.jar /sdcard% adb shell dalvikvm -cp /sdcard
12、/foo.jar FLOGOjava語言是解釋型語言,它是以跨平臺換取執(zhí)行效率為代價的??缙脚_性體現(xiàn)在編譯的跨平臺性和運行跨平臺性。編譯的跨平臺體現(xiàn)在源程序不限制于在某一平臺進行編譯,運行的跨平臺性體現(xiàn)在編譯出來的可執(zhí)行程序也不限制于在某一平臺上運行。這樣神奇是特性是不是特別具有吸引力呢?現(xiàn)在我們把重點放在運行的跨平臺性。運行的跨平臺性是以犧牲虛擬機的平臺性相關(guān)性為代價的,而這正是我們需要解決的問題,因為官方并未提供unicore架構(gòu)的虛擬機。Dalvik虛擬機的平臺相關(guān)性集中的體現(xiàn)在的執(zhí)行引擎上,它是Dalvik虛擬機的核心部分,Dex字節(jié)碼就是在這個部分解釋執(zhí)行 。平臺相關(guān)性問題我們先暫且
13、擱置,因為在下一部分會重點分析Dalvik虛擬機的移植。先來了解一下解釋器是怎么工作的:5、Dalvik虛擬機核心執(zhí)行引擎LOGO如Dex字節(jié)碼add-int/2addr對應(yīng)的架構(gòu)匯編如下: mov r22, rINST #8 r22 #12 r3- B and r22, r22, #15 GET_VREG(r1, r3) r1- vB GET_VREG(r0, r22) r0- vA FETCH_ADVANCE_INST(1) advance rPC, load rINST add r0, r0, r1 GET_INST_OPCODE(ip) extract opcode from rINS
14、T SET_VREG(r0, r22) vAA- r0 GOTO_OPCODE(ip) jump to next instruction#define GET_VREG(_reg, _vreg) ldw _reg, rFP+, _vreg #2#define FETCH_ADVANCE_INST(_count) ldh.w rINST, rPC+, #(_count*2)#define GET_INST_OPCODE(_reg) and _reg, rINST, #255#define SET_VREG(_reg, _vreg) stw _reg, rFP+, _vreg #2#define
15、GOTO_OPCODE(_reg) add pc, rIBASE, _reg #6對應(yīng)的C實現(xiàn)是:HANDLE_OP_X_INT_2ADDR(OP_AND_INT_2ADDR, and, &, 0) OP_END#define OP_END LOGO對應(yīng)的C實現(xiàn)是:#define HANDLE_OP_X_INT_2ADDR(_opcode, _opname, _op, _chkdiv) HANDLE_OPCODE(_opcode /*vA, vB*/) vdst = INST_A(inst); vsrc1 = INST_B(inst); ILOGV(|%s-int-2addr v%d,v%d,
16、 (_opname), vdst, vsrc1); if (_chkdiv != 0) s4 firstVal, secondVal, result; firstVal = GET_REGISTER(vdst); secondVal = GET_REGISTER(vsrc1); if (secondVal = 0) EXPORT_PC(); dvmThrowException(Ljava/lang/ArithmeticException;, divide by zero); GOTO_exceptionThrown(); if (u4)firstVal = 0 x80000000 & seco
17、ndVal = -1) if (_chkdiv = 1) result = firstVal; /* division */ else result = 0; /* remainder */ else result = firstVal _op secondVal; SET_REGISTER(vdst, result); else SET_REGISTER(vdst, (s4) GET_REGISTER(vdst) _op (s4) GET_REGISTER(vsrc1); FINISH(1);LOGO6、 Dalvik虛擬機的移植及優(yōu)化方向Dalvik虛擬機整個架構(gòu)真正意義上與架構(gòu)相關(guān)的地方
18、只有一個,那就是JNICallbridge。這是因為java引入了JNI機制,實現(xiàn)了java到本地方法的直接調(diào)用。這個調(diào)用關(guān)系就涉及以參數(shù)傳遞的問題,如X86架構(gòu)的參數(shù)全是從右至左壓棧傳遞,而ARM架構(gòu)的參數(shù)傳遞則要遵循ATPCS。因此,Dalvik虛擬機的移植到這一步可以說算完成了。注意,此時解釋器是C語言現(xiàn)實的。JNICallbridge的移植需要認真的分析一下HintsEABI.c這個文件,因為這個文件函數(shù)dvmPlatformInvokeHints會解析要地方法列表的第二項:如一個本地方法列表為:static JNINativeMethod methods = “simple”, “(
19、II)I”, (void*)add,;接著,被分析提取出來的參數(shù)列表會傳遞給dvmPlatformInvoke這個函數(shù)。為了效率,這個函數(shù)一般是用匯編完成的。它所在的文件名為:CallEABI.SCallEABI.S和HintsEABI.c位于android/dalvik/vm/arch/xx_ARCHLOGO從前面的介紹知道Dalvik虛擬機最大的優(yōu)化跨平臺性,但以此換取執(zhí)行效率相對低下的劣勢。因此帶來一項新的挑戰(zhàn)Dalvik虛擬機的優(yōu)化。從目前較成熟的技術(shù)來說,Dalvik虛擬機的優(yōu)化可以從兩個大的方面進行。一個方向是軟件優(yōu)化,包括解釋器的匯編重寫解釋器的匯編重寫和引入引入JIT技術(shù)技術(shù);另一個方面就是硬件優(yōu)化了。我們知道,java字節(jié)碼或是dex字節(jié)碼,它們的表現(xiàn)形式相當(dāng)接近匯編,匯編語言能夠由CPU直接執(zhí)行,字節(jié)碼為什么不可以呢?事實上java早已實現(xiàn)該技術(shù)Jazelle DBX (Direct Bytecode eXecution)技術(shù),即允許它們在某些架構(gòu)的硬件上加速執(zhí)行Java bytecode 。因此,在dalvik虛擬機上實現(xiàn)類類Jazelle功能完全是可行的。由于這涉及以硬件的最底層機制的實現(xiàn),所以目前只能作為一項展望了。LOGO