1. 程式人生 > >安卓Dalvik虛擬機器學習(1)----Dalvik虛擬機器執行原理

安卓Dalvik虛擬機器學習(1)----Dalvik虛擬機器執行原理

安卓Dalvik虛擬機器相關知識點總結

0x01 Java虛擬機器與Dalvik虛擬機器的區別

  • Java虛擬機器執行的是Java位元組碼(儲存在class檔案中),Dalvik執行的是Dalvik位元組碼(由Java位元組碼轉化而來,打包到DEX檔案中)。

  • Dalvik可執行檔案更小。
    由於Android SDK中的dx檔案對常量池進行了壓縮,使得相同字串、常量在DEX檔案中只出現一次。

  • Java虛擬機器與Daivik虛擬機器架構不同
    Java虛擬機器基於棧結構,資源開銷大,Dalvik虛擬機器基於暫存器結構,資料由暫存器直接傳遞,這樣的方式比基於棧結構的方式快得多。

這裡介紹以下把java檔案編譯成dex檔案的方法

  • 先把java檔案編譯生成hello.class
javac Hello.java
  • 在執行命令生成dex檔案
dx --dex --output=Hello.dex Hello.class
  • javap對class檔案進行反編譯
javap -c -classpath . Hello
  • 使用Android SDK 工具dexdump檢視函式的位元組碼
dexdump.exe -d Hello.dex

注意事項:筆者使用的JDK1.8,在使用dx生成dex檔案報錯如下:

UNEXPECTED TOP-LEVEL EXCEPTION:
java.lang.RuntimeException:
Helle.class: file not found at com.android.dex.util.FileUtils.readFile(FileUtils.java:51) at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:169) at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:144) at com.android.dx.command
.dexer.Main.processOne(Main.java:596) at com.android.dx.command.dexer.Main.processAllFiles(Main.java:498) at com.android.dx.command.dexer.Main.runMonoDex(Main.java:264) at com.android.dx.command.dexer.Main.run(Main.java:230) at com.android.dx.command.dexer.Main.main(Main.java:199) at com.android.dx.command.Main.main(Main.java:103) 1 error; aborting

錯誤原因:預設生成的Hello.class檔案版本過低。
解決方法:強制指定class檔案的版本,使用如下命令重新編譯

javac -source 1.6 -target 1.6 Hello.java

0x01 Java位元組碼和Dalvik位元組碼的區別

下面這個例子我們對一個簡單的add函式位元組碼進行觀察

  • 首先編寫原始的Java程式碼Hello.java
public class Hello{
   public int add(int a,int b){
    return a + b; 
   }

   public static void main(String[] argc){
    Hello hello = new Hello();
    System.out.println(hello.add(5,3));
   }
}
  • 用上述Javac命令生成java.class,用javap命令反編譯class檔案得出add方法java位元組碼
  public int add(int, int);
    Code:
       0: iload_1
       1: iload_2
       2: iadd
       3: ireturn
  • 用上述的dx命令生成dex檔案,再用dexdump生成Dalvik位元組碼如下
 Hello.add:(II)I
 add-int v0, v2, v3
 return v0

簡單對比:在這裡不對具體的位元組碼語法做講解,我們可以看出Dalvik位元組碼比Java位元組碼看起來簡潔一些,而且可以看出Java虛擬機器是基於棧結構的,Dalvik虛擬機器是基於暫存器結構的,v0, v2, v3代表暫存器

0x02 Dalvik虛擬機器的執行程式流程概述

流程簡單敘述:Dalvik虛擬機器執行緒首先通過loadClassFromDex()函式完成類的裝載工作,每個類被成功解析後會擁有一個ClassObject型別的資料結構儲存在執行環境中,虛擬機器使用gDvm.loadedClasses全域性雜湊表來儲存與查詢所有裝載進來的類,隨後,位元組碼驗證器使用dvmVerifyCodeFlow()函式對裝載的程式碼進行校驗,接著虛擬機器呼叫FindClass()函式查詢並且裝載main方法類,隨後呼叫dvmInterpret()函式初始化直譯器並執行位元組碼流,整個過程如下:
這裡寫圖片描述

好了Dalvik虛擬機器執行原理介紹到此為止,下一章開始進入Dalvik虛擬機器組合語言的學習,如果大家有任何不懂得可以查考《Android軟體安全與逆向分析》第三章