Dalvik,ART與ODEX簡析

如果你有這樣的問題: 1.Dalvik和ART的區別 2.DEX在Dalvik轉化爲ODEX和ART中轉化爲ODEX的過程有上面區別 3.multidex在dalvik上起作用,ART上使用的也是multidex麼(如果不是的話在application中寫入multidex.install會對apk啓動造成影響麼)

如果你比較“懶”,,懶得看老羅的源碼分析,,,長篇大論 請“簡要”看完以下“簡要”內容

一:Dalvik和ART的區別

Dalvik: Dalvik是Google公司自己設計用於Android平臺的Java虛擬機它可以支持已轉換爲 .dex(即Dalvik Executable)格式的Java應用程序的運行,.dex格式是專爲Dalvik設計的一種壓縮格式,適合內存和處理器速度有限的系統。執行的是字節碼,它是依靠Just-In-Time (JIT)機制去解釋字節碼 ART:即Android Runtime,google爲了替代Dalvik專門爲Android研發的。Android KK爲開發者推出,L版本正式上線。比替代品更高效省電,執行的是本地機器碼(也就是linux的ELF文件格式),依靠Ahead-Of-Time (AOT)機制

二.在不同平臺DEX轉化爲ODEX的過程

簡化流程如下:

打包安裝運行簡化流程.png

這裏參考的是

Android ART運行時無縫替換Dalvik虛擬機的過程分析

http://blog.csdn.net/luoshengyang/article/details/18006645

android安裝過程源碼分析:

Android應用程序進程啓動過程的源代碼分析

http://blog.csdn.net/luoshengyang/article/details/6747696

簡單來說,就是Android系統通過PackageManagerService來安裝APK,在安裝的過程,PackageManagerService會通過另外一個類Installer的成員函數dexopt來對APK裏面的dex字節碼進行優化:

public final class Installer {  
    ......  

    public int dexopt(……) {  
        StringBuilder builder = new StringBuilder("dexopt");  
        builder.append(' ');  
        builder.append(apkPath);  
        builder.append(' ');  
        builder.append(uid);  
        builder.append(isPublic ? " 1" : " 0");  
        return execute(builder.toString());  
    }  

    ......  
}

這個函數定義在文件frameworks/base/services/java/com/android/server/pm/Installer.java中。Installer通過socket向守護進程installd發送一個dexopt請求,這個請求是由installd裏面的函數dexopt來處理的。詳細過程請移步Android ART運行時無縫替換Dalvik虛擬機的過程分析

int dexopt(const char ……

函數定義在frameworks/native/cmds/installd/commands.c中 函數dexopt首先是讀取系統屬性persist.sys.dalvik.vm.lib的值,接着在/data/dalvik-cache目錄中創建一個odex文件。這個odex文件就是作爲dex文件優化後的輸出文件。再接下來,函數dexopt通過fork來創建一個子進程。如果系統屬性persist.sys.dalvik.vm.lib的值等於libdvm.so,那麼該子進程就會調用函數run_dexopt來將dex文件優化成odex文件。另一方面,如果系統屬性persist.sys.dalvik.vm.lib的值等於libart.so,那麼該子進程就會調用函數run_dex2oat來將dex文件翻譯成oat文件,實際上就是將dex字節碼翻譯成本地機器碼,並且保存在一個oat文件中。 函數run_dexopt通過調用/system/bin/dexopt來對dex字節碼進行優化,而函數run_dex2oat通過調用/system/bin/dex2oat來將dex字節碼翻譯成本地機器碼。注意,無論是對dex字節碼進行優化,還是將dex字節碼翻譯成本地機器碼,最終得到的結果都是保存在相同名稱的一個odex文件裏面的,但是前者對應的是一個dey文件(表示這是一個優化過的dex),後者對應的是一個oat文件(實際上是一個自定義的elf文件,裏面包含的都是本地機器指令)。通過這種方式,原來任何通過絕對路徑引用了該odex文件的代碼就都不需要修改了。

三.oat文件格式

藉助羅大神的圖我們可以知道,OAT文件本質上是一個ELF文件,因此在最外層它具有一般ELF文件的結構,例如它有標準的ELF文件頭以及通過段(Section)來描述文件內容。

OAT文件包含有兩個特殊的段oatdata和oatexec,前者包含有用來生成本地機器指令的dex文件內容,後者包含有生成的本地機器指令,它們之間的關係通過儲存在oatdata段前面的oat頭部描述。

APK安裝過程中生成的OAT文件的輸入只有一個DEX文件,也就是來自於打包在要安裝的APK文件裏面的classes.dex文件。實際上,一個OAT文件是可以由若干個DEX生成的。這意味着在生成的OAT文件的oatdata段中,包含有多個DEX文件。詳細分析請移步Android運行時ART加載OAT文件的過程分析

四.multidex加載odex,multidex和oat的關係

MultiDex在dalvik虛擬機上的簡要安裝過程: 將/data/app/apkName.apk路徑下解壓得到的classes2.dex, …, classesN.dex,依次寫入到/data/data/pkgName/code_cache/secondary-dexes/apkName.apk.classes2.zip等zip文件的classes.dex中,並返回這個zip列表。然後針對這個zip列表執行安裝過程,具體過程是,將這個要安裝的zip列表加入BaseDexClassLoader的pathList實例的dexElements數組中,其中會針對各dex文件進行dex2opt優化。一旦加入到了dexElements數組中,程序啓動的時候,ClassLoader會加載dexElements數組中的元素,從而實現multi dex的安裝。

上面提到OAT文件可以由若干個dex生成,也就是不需要multidex去進行安裝,但是multidex是application中 進行Install的,跟虛擬機關係不大。

@Override
    attachBaseContext(……) {
    super.attachBaseContext(base);
    MultiDex.install(this);
}

在install函數中在執行從提取dex文件列表前會做一些校驗操作,其中包含檢查APK是否已安裝,若APK已安裝,則不進行後續操作。檢查SDK版本號,版本號大於20不能保證MultiDex可正常Work

 Set var2 = installedApk;
 synchronized(installedApk) {                  
 String apkPath = e.sourceDir;                  
 if(installedApk.contains(apkPath)) {                        
       return;
    }

所以multidex在ART上不會影響程序的邏輯,它和ART沒有關係~。。。。 multidex源碼分析:MultiDex安裝過程源碼分析

小結:

從安裝過程上來看 Java的代碼實際上需要兩次“轉換”纔可以在android設備上運行 一.PC端:.class->.dex->.apk 二.phone:dex->odex

區別在於第二步。 ART : .dex->.odex(機器碼)(AOT  Ahead-Of-Time) Dalvik: .dex->.odex(字節碼)(JIT Just-In-Time) 機器碼可直接執行,而字節碼每次啓動都需要執行將優化過的odex字節碼再轉換成機器碼

ART優缺

系統性能大幅提升 App啓動、運行更快 減少每次啓動的編譯增加電池續航 存儲佔用更大 安裝時間更長

複製粘貼+理解,,,希望以後忘了能回來看看~!~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章