若是你有這樣的問題:
1.Dalvik和ART的區別
2.DEX在Dalvik轉化爲ODEX和ART中轉化爲ODEX的過程有上面區別
3.multidex在dalvik上起做用,ART上使用的也是multidex麼(若是不是的話在application中寫入multidex.install會對apk啓動形成影響麼)javascript
若是你比較「懶」,,懶得看老羅的源碼分析,,,長篇大論
請「簡要」看完如下「簡要」內容java
一: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)機制linux
二.在不一樣平臺DEX轉化爲ODEX的過程
簡化流程以下:
android
打包安裝運行簡化流程.pngweb
這裏參考的是數組
Android ART運行時無縫替換Dalvik虛擬機的過程分析微信
http://blog.csdn.net/luoshengyang/article/details/18006645app
android安裝過程源碼分析:socket
Android應用程序進程啓動過程的源代碼分析ide
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啓動、運行更快
減小每次啓動的編譯增長電池續航
存儲佔用更大
安裝時間更長
複製粘貼+理解,,,但願之後忘了能回來看看~!~
本文分享自微信公衆號 - 喘口仙氣(gh_db8538619cdd)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。