天天看點

Android(java)學習筆記99:Java虛拟機和Dalvik虛拟機的差別

Google于2007年底正式釋出了Android SDK, 作為 Android系統的重要特性,Dalvik虛拟機也第一次進入了人們的視野。它對記憶體的高效使用,和在低速CPU上表現出的高性能,确實令人刮目相看。 依賴于底層Posix相容的作業系統,它可以簡單的完成程序隔離和線程管理。每一個Android應用在底層都會對應一個獨立的Dalvik虛拟機執行個體, 其代碼在虛拟機的解釋下得以執行。 

很多人認為Dalvik虛拟機是一個Java虛拟機,因為Android的程式設計語言恰恰就是Java語言。但是這種說法并不準确,因為Dalvik虛拟機并不是按照Java虛拟機的規範來實作的,兩者并不相容;同時還要兩個明顯的不同:

Java虛拟機運作的是Java位元組碼,生成的位元組碼檔案也就是class檔案(class檔案:二進制處理過的檔案),然後再由java虛拟機去執行編譯運作過程。而Dalvik虛拟機運作的則是其專有的檔案格式DEX(Dalvik Executable)。

在Java SE程式中的Java類會被編譯成一個或者多個位元組碼檔案(.class)然後打包到JAR檔案,而後Java虛拟機會從相應的CLASS檔案和JAR文 件中擷取相應的位元組碼;Android應用雖然也是使用Java語言進行程式設計,但是在編譯成CLASS檔案後,還會通過一個工具(dx)将應用所有的 CLASS檔案轉換成一個.dex檔案(dex檔案是壓縮成zip檔案,這樣可以減少占用空間),而後Dalvik虛拟機會從其中讀取指令和資料。

Dalvik和Android系統Android作為新一代的基于Linux的開源手機作業系統,其系統架構由下而上可以分為以下幾部分:

1)Linux核心

2)本地庫

3)Android運作庫

4)應用架構

5)應用    

Dalvik VM (Android虛拟機),它可以支援已轉換為.dex(即Dalvik Exacutable)格式的java應用程式。.dex格式是專為Dalvik設計的一種壓縮格式,适合記憶體和處理器速度有限的系統。

每一個Android應用都運作在一個Dalvik VM執行個體裡,而每一個虛拟機執行個體都是一個獨立的程序空間。虛拟機的線程機制、記憶體配置設定和管理、Mutex等都是依賴底層作業系統實作的。所有Android應用的線程都對應一個Linux線程,虛拟機因而可以更多依賴操作的線程排程和管理機制。

Java虛拟機和Dalvik虛拟機的差別:

java虛拟機

Dalvik虛拟機

java虛拟機基于棧。 基于棧的機器必須使用指令來載入和操作棧上資料,所需指令更多更多

dalvik虛拟機是基于寄存器的

java虛拟機運作的是java位元組碼。(java類會被編譯成一個或多個位元組碼.class檔案,打包到.jar檔案中,java虛拟機從相應的.class檔案和.jar檔案中擷取相應的位元組碼)

Dalvik運作的是自定義的.dex位元組碼格式。(java類被編譯成.class檔案後,會通過一個dx工具将所有的.class檔案轉換成一個.dex檔案,然後dalvik虛拟機會從其中讀取指令和資料)

常量池已被修改為隻使用32位的索引,以 簡化解釋器。dalvik的堆和棧的參數可以通過-Xms和-Xmx更改

一個應用,一個虛拟機執行個體,一個程序(所有android應用的線程都是對應一個linux線程,都運作在自己的沙盒中,不同的應用在不同的程序中運作。每個android dalvik應用程式都被賦予了一個獨立的linux PID(app_*))

Dalvik和标準Java虛拟機(JVM)之間的首要差别之一,就是Dalvik基于寄存器,而JVM基于棧。Dalvik基于寄存器指令體大,但是指令不多。JVM指令體小,但是指令多。

Dalvik和Java之間的另外一大差別就是運作環境——Dalvik經過優化,允許在有限的記憶體中同時運作多個虛拟機的執行個體,并且每一個 Dalvik應用作為一個獨立的Linux程序執行。

(1)虛拟機很小,使用的空間也小;

(2)Dalvik沒有JIT編譯器;

(3)常量池已被修改為隻使用32位的索引,以簡化解釋器;

(4)它使用自己的位元組碼,而非Java位元組碼。

 備注:

JIT編譯器,英文寫作Just-In-Time Compiler,中文意思是即時編譯器。

JIT編譯器能夠将MSIL編譯成為各種不同的機器代碼,以适應對應的系統平台,最終使得程式在目标系統中得到順利地運作。

Dalvik虛拟機架構:

  在android源碼中,Dalvik虛拟機的實作位于“dalvik/”目錄下,其中“dalvik/vm”是虛拟機的實作部分,将會編譯成libdvm.so;而"dalvik/libdex"将會編譯成libdex.a靜态庫作為dex工具;“dalvik/dexdump”是.dex檔案的反編譯工具;虛拟機的可執行程式位于“dalvik/dalvikvm”中,将會編譯成dalvikvm可執行檔案。

  dalvik虛拟機架構:

Android應用編譯及運作流程:

Dalvik程序管理:

   dalvik程序管理是依賴于linux的程序體系結構的,如要為應用程式建立一個程序,它會使用linux的fork機制來複制一個程序(複制程序往往比建立程序效率更高)。

   Zygote是一個虛拟機程序,同時也是一個虛拟機執行個體的孵化器,它通過init程序啟動。首先會孵化出System_Server(android絕大多系統服務的守護程序,它會監聽socket等待請求指令,當有一個應用程式啟動時,就會向它送出請求,zygote就會FORK出一個新的應用程式程序).每當系統要求執行一個android應用程式時,Zygote就會運用linux的FORK進制産生一個子程序來執行該應用程式。

   每當執行一個Android應用程式,Zygote就會孵化一個子線程去執行該應用程式(系統内部執行dvz指令完成的)。這樣做的好處是顯而易見的,Zygote程序是在系統啟動時産生的,它會完成虛拟機的初始化,庫的加載,預置類庫的加載和初始化等操作,而在系統需要一個新的虛拟機執行個體時,Zygote通過複制自身,最快速地提供一個系統。另外,對于一些隻讀的系統庫,所有虛拟機執行個體都和Zygote共享一塊記憶體區域,這樣可以大大節省記憶體開銷。

   相對于基于堆棧的虛拟機實作,基于寄存器的虛拟機實作雖然在硬體通用性上要差一些,但是它在代碼的執行效率卻更勝一籌。在基于寄存器的虛拟機中,可以更加有效地減少多餘指令的分發和減少記憶體的讀寫通路。

JVM和Dalvik程序管理:

   linux中程序間通信的方式有很多,但是dalvik使用的是信号方式來完成程序間通信。