Android 源碼分析(十) Dalvik 虛擬機器建立過程

來源:互聯網
上載者:User

標籤:his   vol   pack   profile   create   android應用   裝置   save   方式   

一. 介紹Dalvik

  1.java的運行需要JVM(後面有大量篇幅介紹),同樣android中使用了java語言,也需要一個VM。針對手機處理器和記憶體等硬體資源不足而推出來的一款VM,為android運行提供環境,叫DVM。

  2.Dalvik虛擬機器允許多個instance的存在。實際上android中的每一個app都是運行在自己VM執行個體之中(沙箱)。每一個VM執行個體在linux中又是一個單獨的進程,所以可以認為是同一個概念。運行在自己的DVM進程之中,不同的app不會相互幹擾,且不會因為一個DVM的崩潰導致所有的app進程都崩潰。這點來說,Android dvm的進程和Linux的進程, 應用程式的進程 概念類似。

  3.與JVM的區別:

    1.基於架構的不同。JVM是基於棧的架構,而DVM是基於寄存器架構。

    2.jvm啟動並執行是位元組碼檔案,而dvm運行自己定義的dex檔案格式。

      JVM編譯過程 java->class->jar
       DVM編譯過程java->class->dex

    總結dvm與jvm區別:     

    區別一:dvm執行的是.dex格式檔案  jvm執行的是.class檔案   android程式編譯完之後生產.class檔案,然後,dex工具會把.class檔案處理成.dex檔案,然後把資源檔和.dex檔案等打包成.apk檔案。apk就是android package的意思。 jvm執行的是.class檔案。

 

    區別二:dvm是基於寄存器的虛擬機器  而jvm執行是基於虛擬棧的虛擬機器。寄存器存取速度比棧快的多,dvm可以根據硬體實現最大的最佳化,比較適合行動裝置。

 

    區別三:.class檔案存在很多的冗餘資訊,dex工具會去除冗餘資訊,並把所有的.class檔案整合到.dex檔案中。減少了I/O操作,提高了類的尋找速度

    

    一張圖瞭解dvm主要做的事:

    

    參考: 47682797

二.Dalvik啟動過程

  

//AndroidRuntime.cppint AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote){    JavaVMInitArgs initArgs;    char propBuf[PROPERTY_VALUE_MAX];    char stackTraceFileBuf[sizeof("-Xstacktracefile:")-1 + PROPERTY_VALUE_MAX];    char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];    char heapstartsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];    char heapsizeOptsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];    char heapgrowthlimitOptsBuf[sizeof("-XX:HeapGrowthLimit=")-1 + PROPERTY_VALUE_MAX];    char heapminfreeOptsBuf[sizeof("-XX:HeapMinFree=")-1 + PROPERTY_VALUE_MAX];    char heapmaxfreeOptsBuf[sizeof("-XX:HeapMaxFree=")-1 + PROPERTY_VALUE_MAX];    char usejitOptsBuf[sizeof("-Xusejit:")-1 + PROPERTY_VALUE_MAX];    char jitmaxsizeOptsBuf[sizeof("-Xjitmaxsize:")-1 + PROPERTY_VALUE_MAX];    char jitinitialsizeOptsBuf[sizeof("-Xjitinitialsize:")-1 + PROPERTY_VALUE_MAX];    char jitthresholdOptsBuf[sizeof("-Xjitthreshold:")-1 + PROPERTY_VALUE_MAX];    char useJitProfilesOptsBuf[sizeof("-Xjitsaveprofilinginfo:")-1 + PROPERTY_VALUE_MAX];    char jitprithreadweightOptBuf[sizeof("-Xjitprithreadweight:")-1 + PROPERTY_VALUE_MAX];    char jittransitionweightOptBuf[sizeof("-Xjittransitionweight:")-1 + PROPERTY_VALUE_MAX];    char gctypeOptsBuf[sizeof("-Xgc:")-1 + PROPERTY_VALUE_MAX];    char backgroundgcOptsBuf[sizeof("-XX:BackgroundGC=")-1 + PROPERTY_VALUE_MAX];    char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];    char cachePruneBuf[sizeof("-Xzygote-max-boot-retry=")-1 + PROPERTY_VALUE_MAX];    char dex2oatXmsImageFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];    char dex2oatXmxImageFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];    char dex2oatXmsFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];    char dex2oatXmxFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];    char dex2oatCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX];    char dex2oatImageCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX];    char dex2oatThreadsBuf[sizeof("-j")-1 + PROPERTY_VALUE_MAX];    char dex2oatThreadsImageBuf[sizeof("-j")-1 + PROPERTY_VALUE_MAX];    char dex2oat_isa_variant_key[PROPERTY_KEY_MAX];    char dex2oat_isa_variant[sizeof("--instruction-set-variant=") -1 + PROPERTY_VALUE_MAX];    char dex2oat_isa_features_key[PROPERTY_KEY_MAX];    char dex2oat_isa_features[sizeof("--instruction-set-features=") -1 + PROPERTY_VALUE_MAX];    char dex2oatFlagsBuf[PROPERTY_VALUE_MAX];    char dex2oatImageFlagsBuf[PROPERTY_VALUE_MAX];    char extraOptsBuf[PROPERTY_VALUE_MAX];    char voldDecryptBuf[PROPERTY_VALUE_MAX];    ...        /*     * Initialize the VM.     *     * The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.     * If this call succeeds, the VM is ready, and we can start issuing     * JNI calls.     */    if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {        ALOGE("JNI_CreateJavaVM failed\n");        return -1;    }    return 0;}void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote){        /* start the virtual machine */    JniInvocation jni_invocation;    jni_invocation.Init(NULL);    JNIEnv* env;    if (startVm(&mJavaVM, &env, zygote) != 0) {        return;    }    onVmCreated(env);    /*     * Register android functions.     */    if (startReg(env) < 0) {        ALOGE("Unable to register all android natives\n");        return;    }}

     //Dalvik虛擬機器在Zygote進程中的啟動過程,這個啟動過程主要就是完成了以下四個事情:
        //1. 建立了一個Dalvik虛擬機器執行個體;
        //2. 載入了Java核心類及其JNI方法;
        //3. 為主線程的設定了一個JNI環境;
        //4. 註冊了Android核心類的JNI方法。

Zygote 啟動Dalvik作用:

  1. Zygote進程為Android系統準備好了一個Dalvik虛擬機器執行個體,以後Zygote進程在建立Android應用程式進程的時候,就可以將它自身的Dalvik虛擬機器執行個體複製到新建立Android應用程式進程中去,從而加快了Android應用程式進程的啟動過程。


  2.Java核心類和Android核心類(位於dex檔案中),以及它們的JNI方法(位於so檔案中),都是以記憶體映射的方式來讀取的,因此,Zygote進程在建立Android應用程式進程的時候,除了可以將自身的Dalvik虛擬機器執行個體複製到新建立的Android應用程式進程之外,還可以與新建立的Android應用程式進程共用Java核心類和Android核心類,以及它們的JNI方法,這樣就可以節省記憶體消耗。


  3.Zygote進程為了加快Android應用程式進程的啟動過程,犧牲了自己的啟動速度,因為它需要載入大量的Java核心類,以及註冊大量的Android核心類JNI方法。Dalvik虛擬機器在載入Java核心類的時候,還需要對它們進行驗證以及最佳化,這些通常都是比較耗時的。又由於Zygote進程是由init進程啟動的,也就是說Zygote進程在是開機的時候進行啟動的,因此,Zygote進程的犧牲是比較大的。不過畢竟我們在玩手機的時候,很少會關機,也就是很少開機,因此,犧牲Zygote進程的啟動速度是值得的,換來的是Android應用程式的快速啟動。

Android 源碼分析(十) Dalvik 虛擬機器建立過程

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.