逆向基礎------Dalvik可執行格式

知道學的是啥,有啥用,在平時生活中扮演什麼角色時,就會主動想去學了。

雖然Android系統採用Java語言來開發應用程序,但Android程序卻不是運行在傳統的Java虛擬機上的。

可能爲了解決與Oracle版本問題,或者是Java虛擬機在設備上卡頓問題,Google對Android系統設計了專屬的虛擬機,從Android4.4開始引入了ART(Android RunTime)虛擬機,將由JIT(實時編譯)執行的Dalvik虛擬機切換爲由AOT編譯的ART,爲了向下兼容,ART也支持Dalvik格式和字節碼的支持。Dalvik虛擬機目前仍然是需要重點研究的對象。這就解釋了什麼是Dalvik,以及爲什麼我要學Dalvik彙編語言知識了。

一、Dalvik虛擬機的特點

  • 1、體積小,佔用內存空間小

  • 2、專有的DEX(Dalvik Executable)可執行文件格式,體積小,執行速度快。

  • 3、常量池採用32位索引值,對類方法名、字段名、常亮的尋址速度快。

  • 4、基於寄存器架構,同時擁有一套完整的指令系統(Dalvik彙編)

  • 5、提供了對象生命週期管理、堆棧管理、線程管理、安全和異常管理及垃圾回收等重要功能。

  • 6、所有的Android程序都運行在Android系統進程中,每個進程都與一個Dalvik虛擬機實例對應。

對以上內容會有一一對應的解釋。

二、Dalvik虛擬機與Java虛擬機的區別

1、運行的字節碼不同

Java虛擬機運行的是Java字節碼,Dalvik虛擬機運行的是Dalvik字節碼(可以理解爲彙編)。

傳統的Java程序經過編譯,生成Java字節碼並保存在class文件中,Java虛擬機通過解碼Class文件內容運行程序;

Dalvik虛擬機運行的Dalvik字節碼是由Java字節碼轉換而來,並被打包到一個DEX可執行文件中(爲什麼使用JEB反編譯DEX文件,就是通過DEX還原源JAVA代碼),Dalvik虛擬機通過解釋DEX文件來執行這些字節碼。

2、Dalvik可執行文件的體積更小

爲什麼Dalvik可執行文件dex體積更小?
在Android SDK中,將Java字節碼轉換爲Dalvik字節碼的工具是"dx"。dx能夠重新排列Java類文件,消除在類文件中的冗餘信息,避免重複加載和解析。

原理是這樣子的:
Java類中通常有多個方法簽名,如果它被調用或者繼承,這些簽名和方法也會被繼承在調用方,所以大量的類包含同樣的簽名和字符串常量造成冗餘。DX把這些常量統一存放在"常量池"中,一個常量只出現一次,供所有類使用,所以DEX文件體積更小。

3、虛擬機架構不同

Java虛擬機基於棧架構,運行時指令頻繁入棧和出棧,佔用大量CPU時間,對於資源有限的設備資源比較吃緊。

而Dalvik是基於寄存器架構的,指令發送給寄存器。總所周知,直接操作寄存器的彙編語言執行速度是最快的。因爲是搞逆向的,甭指望直接搞到源碼,所以要會彙編,反推源代碼邏輯,所以要學Dalvik彙編指令。

4、虛擬機執行流程

對所要研究的東西研究更深入一些,知其然知其所以然,遇到問題就不會慌。

Android系統架構圖。
在這裏插入圖片描述
所有的與硬件的驅動都基於Linux內核,"所有皆文件"的linux設計理念,方便於其他系統集成。

Libray通用庫、上層框架和應用層暫沒研究。

着重Dalvik虛擬機。

Dalvik屬於Android運行時環境。
在這裏插入圖片描述
Zygote是所有進程的孵化器,應用程序通過system_server將指令發給Zygote,Zygote爲其分配一個單獨的進程,並由Dalvik執行。

Dalvik通過loadClassFromDex()裝載類。類被解析後變成ClassObject類型的數據結構存儲,虛擬機採用gDvm.loadedClass全局散列表(類似map)存儲和查詢。

字節碼驗證器使用dvmVerifyCodeFlow()函數對裝入的代碼進行校驗,虛擬機調用FindClass()函數查找並找到main()方法類。最後調用dvmInterpret()函數來初始化解釋器並執行字節流。

5、虛擬機執行方式

即時編譯。參考C++和C編譯的感人速度,就知道虛擬機的即時編譯多麼重要。尤其C++是將所有的代碼編成字節碼後再運行,即時編譯是在運行時編譯字節碼,使程序的執行速度加快。

發佈了50 篇原創文章 · 獲贊 33 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章