本文通過(guò)學(xué)習(xí):聊聊 APK —— 直接運(yùn)行 Dex 總結(jié)。
1.運(yùn)行工具分析
在java學(xué)習(xí)時(shí),如果想順利的運(yùn)行java程序,需要安裝JRE,對(duì)于開發(fā)者而言,需要安裝JDK,但最終執(zhí)行Java程序的是在JVM中運(yùn)行。將**.java文件轉(zhuǎn)為一個(gè)或多個(gè)字節(jié)碼.class文件,然后將其打包到.jar包中,JVM從相應(yīng)的.class文件和.jar中獲取相應(yīng)的字節(jié)碼。
.java---.class--JVM運(yùn)行加載
對(duì)于Android程序,除了將.java文件轉(zhuǎn)為.class文件外,還需要在.class文件的基礎(chǔ)上轉(zhuǎn)為.dex(Dalvik Execuable)格式,該格式是轉(zhuǎn)為Dalvik設(shè)計(jì)的,適合內(nèi)存和處理器速度有限的系統(tǒng)中運(yùn)行,同時(shí)Dalvik允許在有限的內(nèi)存中同時(shí)運(yùn)行多個(gè)虛擬機(jī)實(shí)例,每個(gè)實(shí)例作為獨(dú)立的Linux進(jìn)程執(zhí)行,互相之間不影響(安卓中的APP,每個(gè)APP運(yùn)行在獨(dú)立的虛擬機(jī)實(shí)例中,作為獨(dú)立的Linux進(jìn)程)。
.java---.class--.dex--ART/Dalvik運(yùn)行加載
安卓中有兩種虛擬機(jī)Dalvik和ART,其中ART(Android Runtime)是在2014年I/O大會(huì)上正式代替Dalvik,兩者區(qū)別如下:
| 對(duì)比項(xiàng) | ART | Dalvik |
|---|---|---|
| 安裝 | 安裝時(shí)間久,占用內(nèi)存空間大 | 安裝時(shí)間較短,占用內(nèi)存空間較小 |
| 編譯 | 預(yù)編譯(AOT:Ahead-Of-Time ) :應(yīng)用在第一次安裝時(shí)字節(jié)碼預(yù)先編譯成機(jī)器碼 | 運(yùn)行時(shí)編譯(JIT:Just-In-Time) :在每次運(yùn)行時(shí)編譯 |
| 運(yùn)行 | 運(yùn)行效率較高,不需要再次編譯字節(jié)碼(空間換時(shí)間) | 運(yùn)行效率較低,需要每次編譯字節(jié)碼(時(shí)間換空間) |
| 性能 | 減少編譯,手機(jī)電池續(xù)航能力和CPU運(yùn)行效率提高 | 耗費(fèi)較多電量和cpu資源 |
以下關(guān)于安卓運(yùn)行的虛擬機(jī)都簡(jiǎn)稱為Dalvik。
2、Java運(yùn)行
在文本中編輯一個(gè).java的程序,如下所示:
public class HelloWorld {
public static void main (String [] args){
System.out.println("Hello World!");
}
}
在cmd中通過(guò)javac命令將其轉(zhuǎn)為.class文件,如果運(yùn)行javac命令不成功,可參考javac配置后通過(guò)cmd操作時(shí)顯示不是內(nèi)部命令。
javac HelloWorld.java
生成.class文件后,執(zhí)行java命令后,會(huì)打印出程序中運(yùn)行的輸出字段。如下所示:
java -cp . HelloWorld

以上操作是在HelloWorld.java所在的目錄中運(yùn)行的,如在其他文件中運(yùn)行,需要先指定文件目錄,否則會(huì)提示“錯(cuò)誤: 找不到或無(wú)法加載主類 HelloWorld”,上面語(yǔ)句中的“cp”
就是類似于classpath的意思,指明文件的目錄。例如將cmd切換至C根目錄,則執(zhí)行如下語(yǔ)句:
java -cp C:\Users\XK\Desktop\APKtest\ HelloWorld
其中HelloWorld位于桌面(Desktop)的APKtest文件中,在指定目錄時(shí),需要注意按照以下方式:
java空格 -cp 空格C:\Users\XK\Desktop\APKtest(文件根目錄)\空格 HelloWorld

3、Android中運(yùn)行
3.1生成dex文件
在第二部分中生成的.class文件,需要通過(guò)dx生成dex文件,才可運(yùn)行在Dalvik中。在AndroidStudio開發(fā)時(shí),該IDE自動(dòng)將文件幫我們轉(zhuǎn)換好,可通過(guò)查看Project Structure中SDK Location\build-tools,獲取版本信息,如下所示:
這里使用28.0.3中的dx.bat生成dex文件,直接在該目錄打開cmd,并執(zhí)行如下所示:
dx --dex --output=classes.dex HelloWorld.class
dx可以將class文件轉(zhuǎn)為.dex.jar.apk.zip。
3.2 運(yùn)行dex文件
將生成的dex文件push至手機(jī)的sdcard目錄下,如下所示:
adb push classes.dex /sdcard
通過(guò)class文件和dex文件生成的過(guò)程可以看出一個(gè)class文件由java生成,dex由class文件生成,class文件中包含多個(gè)public類,因此dex文件類似,其可以包含多個(gè)class文件,類似于jar。其過(guò)程類比于文件的壓縮過(guò)程。
將dex推送至手機(jī)目錄后,執(zhí)行adb shell,進(jìn)入sdcard目錄,執(zhí)行如下執(zhí)行,就會(huì)打印為程序運(yùn)行的HelloWorld!信息。
HWSTF:/sdcard $ dalvikvm -cp classes.dex HelloWorld
Hello World!