Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android中dex文件的加載與優化流程

Android中dex文件的加載與優化流程

編輯:關於Android編程

1、dex文件分析

邏輯上,可以把dex文件分成3個區,頭文件、索引區和數據區。索引區的ids後綴為identifiers的縮寫。

\

 

header

dex文件裡的header。除了描述.dex文件的文件信息外,還有文件裡其他各個區域的索引。

\

 

(1)magic value,這8個字節一般是常量,為了使.dex文件能夠被識別出來,它必須出現在.dex文件的最開頭的位置。

(2)checksum和signature.文件校驗碼,使用alder32算法校驗文件出去maigc,checksum外余下的所有文件區域,用於校驗文件錯誤。Signature,使用SHA-1算法hash除去magic,checksum和signature外余下的所有文件區域。

(3)file_size:Dex文件的大小。

其余的屬性,因為在加固中沒有用到。這裡就不對它們進行過多解釋。

2、odex文件

odex是OptimizedDEX的縮寫,表示經過優化的dex文件。存放在/data/dalvik-cache目錄下。由於Android程序的apk文件為zip壓縮包格式,Dalvik虛擬機每次加載它們時需要從apk中讀取classes.dex文件,這樣會耗費很多cpu時間,而采用odex方式優化的dex文件,已經包含了加載dex必須的依賴庫文件列表,Dalvik虛擬機只需檢測並加載所需的依賴庫即可執行相應的dex文件,這大大縮短了讀取dex文件所需的時間。

不過,這個優化過程會根據不同設備上Dalvik虛擬機的版本、Framework庫的不同等因素而不同。在一台設備上被優化過的ODEX文件,拷貝到另一台設備上不一定能夠運行。

2.1、odex文件結構

Odex文件的結構可以理解為dex文件的一個超集。它的結構如下圖所示,odex文件在dex文件頭部添加了一些數據,然後在dex文件尾部添加了dex文件的依賴庫以及一些輔助數據。

 

    \

Dalvik虛擬機將dex文件映射到內存中後是Dalvik格式,在Android系統源碼的dalvik/libdex/DexFile.h文件中它的定義如下。

DexFile結構中存入的多為其他結構的指針。DexFile最前面的DexOptHeader就是odex的頭,DexLink以下的部分被成為auxillary section,即輔助數據段,它記錄了dex文件被優化後添加的一些信息。然而,DexFile結構描述的是加載進內存的數據結構,還有一些數據是不會加載進內存的,經過分析,odex文件結構定義整理如下.

\

Struct ODEXFile{

DexOptHeader header; /*odex文件頭*/

DEXFile dexfile; /*dex文件*/

Dependences deps; /*依賴庫列表*/

ChunkDexClassLookup lookup; /*類查詢結構*/

ChunkRegisterMapPool mappool; /*映射池*/

ChunkEnd end;/*結束標志*/

};

2.2、odex文件結構分析

ODEXFile的文件頭DexOptHeader在DexFile.h文件中定義如下.

struct DexOptHeader{

u1 magic[8]; /*odex版本標識 */

u4 dexOffset; /* dex文件頭偏移*/

u4 dexLength;/* dex文件總長度*/

u4 depsOffset; /*odex依賴庫列表偏移*/

u4 depsLength;/*依賴庫列表總長度*/

u4 optOffset; /*輔助數據偏移*/

u4 optLength; /*輔助數據總長度*/

u4 flags ; /*標志*/

u4 checksum; /*依賴庫與輔助數據的校驗和*/

};

3、dex文件的驗證與優化

3.1 dex文件加載流程

Android提供了一個專門驗證與優化dex文件的工具dexopt。其源碼位於Android系統源碼的dalvik/dexopt目錄下,Dalvik虛擬機在加載一個dex文件時,通過指定的驗證與優化選項來調用dexopt進行相應的驗證與優化操作。

dexopt的主程序為OptMain.cpp,其中處理apk/jar/zip文件中的classes.dex的函數為extractAndProcessZip(),extractAndProcessZip()首先通過dexZipFindEntry()函數檢查目標文件中是否擁有class.dex,如果沒有就失敗返回,成功的話就調用dexZipGetEntryInfo()函數來讀取classes.dex的時間戳與crc校驗值,如果這一步沒有問題,接著調用dexZipExtractEntryTo-File()函數釋放classes.dex為緩存文件,然後開始解析傳遞過來的驗證與優化選項,驗證選項使用“v=”指出,優化選項使用“o=”指出。所有的預備工作都做完後,調用dvmPrepForDexOpt()函數啟動一個虛擬機進程,在這個函數中,優化選項dexOptMode與驗證選項varifyMode被傳遞到了全局DvmGlobals結構gDvm的dexOptMode與classVerifyMode字段中。這時候所有的初始化工作已經完成,dexopt調用dvmContinueOptimization()函數開始真正的驗證和優化工作。

dvmContinueOptimization()函數的調用鏈比較長。首先從OptMain.cpp轉移到、dalvik/vm/analysis/DexPrepare.cpp,因為這裡有dvmContinueOptimization()函數的實現。函數首先對dex文件做簡單的檢查,確保傳遞進來的目標文件屬於dex或odex,接著調用mmap()函數將整個文件映射到內存中,然後根據gDvm的dexOptMode與classVerifyMode字段來設置doVarify與doOpt兩個布爾值,接著調用rewriteDex()函數來重寫dex文件,這裡的重寫內容包括字符調整、結構重新對齊、類驗證信息以及輔助數據。rewriteDex()函數調用dexSwapAndVerify()調整字節序,接著調用dvmDexFileOpenPartial()創建DexFile結構,dvmDexFileOpenPartial()函數的實現在Android系統源碼dalvik/vm/DvmDex.cpp文件中,該函數調用dexFileParse()函數解析dex文件,dexFileParse()函數讀取dex文件的頭部,並根據需要調用驗證dexComputeChecksum()函數或調用dexComputeOptChecksum()函數來驗證dex或odex文件愛你頭的checksum與signature字段。

接著回到DvmDex.cpp文件繼續看代碼,當驗證成功後,dvmDexFileOpenPartial()函數調用allocateAuxStructures()函數設置DexFile結構輔助數據的相關字段,最後執行完後返回到rewriteDex()函數。rewriteDex()接下來調用loadAllClasses()加載dex文件中所有的類,如果這一步失敗了,程序等不到後面的優化與驗證就退出了,如果沒有錯誤發生,會調用verifyAndOptimizeClasses()函數進行真正的驗證工作,這個函數會調用verifyAndOptimizeClass()函數來優化與驗證具體的類,而verifyAndOptimizeClass()函數會細分這些工作,調用dvmVerifyClass()函數進行驗證,再調用dvmOptimizeClass()函數進行優化。

dvmVerifyClass()函數的實現代碼位於Android系統源碼的dalvik/vm/analysis/DexVerify.cpp文件中。這個函數調用verifyMethod()函數對類的所有直接方法與虛方法進行驗證,verifyMethod()函數具體的工作是先調用verifyInstructions()函數來驗證方法中的指令及其數據的正確性,再調用dvmVerifyCodeFlow()函數來驗證代碼流的正確性。

dvmOptimizeClass()函數的實現代碼位於Android系統源碼的dalvik/vm/analysis/Optimize.cpp文件愛你中。這個函數調用optimizeMethod()函數對類的所有直接方法與虛方法進行優化,優化的主要工作是進行“指令替換”,替換原則的優先級為“volatile”替換-正確性替換-高性能替換。比如指令iget-wide會根據優先級替換為“volatile”形式的iget-wide-volatile,而不是高性能的iget-wide-quick.

rewriteDex函數返回後,會再次調用dvmDexFileOpenPartial()來驗證odex文件,接著調用dvmGenerateRegisterMaps()函數來填充輔助數據區結構,填充結構完成後,接下來調用updateChecksum()函數重寫dex文件愛你的checksum值,再往下就是writeDependencies()與writeOptData()了。

3.2 dex文件優化加載流程圖

\

\

\

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved