一圖讀懂JVM架構解析
每個Java開發人員都知道字節碼經由JRE(Java運行時環境)執行。但他們或許不知道JRE其實是由Java虛擬機(JVM)實現,JVM分析字節碼,解釋并執行它。作為開發人員,了解JVM的架構是非常重要的,因為它使我們能夠編寫出更高效的代碼。本文中,我們將深入了解Java中的JVM架構和JVM的各個組件。
JVM
虛擬機是物理機的軟件實現。Java的設計理念是WORA(Write Once Run Anywhere,一次編寫隨處運行)。編譯器將Java文件編譯為Java .class文件,然后將.class文件輸入到JVM中,JVM執行類文件的加載和執行的操作。請看以下的JVM架構圖:
JVM是如何工作的?
如上面架構圖所示,JVM分為三個主要子系統:
- 類加載器子系統(Class Loader Subsystem)
- 運行時數據區(Runtime Data Area)
- 執行引擎(Execution Engine)
1. 類加載器子系統
Java的動態類加載功能由類加載器子系統處理,處理過程包括加載和鏈接,并在類文件運行時,首次引用類時就開始實例化類文件,而不是在編譯時進行。
1.1 加載
Boot Strap類加載器,Extension類加載器和Application(類加載器是實現類加載過程的三個類加載器。
(1) Boot Strap類加載器:負責從引導類路徑加載類,除了rt.jar,它具有最高優先級;
(2) Extension 類加載器:負責加載ext文件夾(jre \ lib)中的類;
(3) Application類加載器:負責加載應用程序級類路徑,環境變量中指定的路徑等信息。
上面的類裝載器在加載類文件時遵循委托層次算法(Delegation Hierarchy Algorithm)。
1.2 鏈接
(1) 驗證(Verify):字節碼驗證器將驗證生成的字節碼是否正確,如果驗證失敗,將提示驗證錯誤;
(2) 準備(Prepare):對于所有靜態變量,內存將會以默認值進行分配;
(3) 解釋(Resolve):有符號存儲器引用都將替換為來自方法區(Method Area)的原始引用。
1.3 初始化
這是類加載的最后階段,所有的靜態變量都將被賦予原始值,并且靜態區塊將被執行。
2. 運行時數據區
運行時數據區可分為5個主要組件:
(1) 方法區(Method Area):所有的類級數據將存儲在這里,包括靜態變量。每個JVM只有一個方法區,它是一個共享資源;
(2) 堆區域(Heap Area):所有對象及其對應的實例變量和數組將存儲在這里。每個JVM也只有一個堆區域。由于方法和堆區域共享多個線程的內存,所存儲的數據不是線程安全的;
(3) 堆棧區(Stack Area):對于每個線程,將創建單獨的運行時堆棧。對于每個方法調用,將在堆棧存儲器中產生一個條目,稱為堆棧幀。所有局部變量將在堆棧內存中創建。堆棧區域是線程安全的,因為它不共享資源。堆棧框架分為三個子元素:
- 局部變量數組(Local Variable Array):與方法相關,涉及局部變量,并在此存儲相應的值
- 操作數堆棧(Operand stack):如果需要執行任何中間操作,操作數堆棧將充當運行時工作空間來執行操作
- 幀數據(Frame Data):對應于方法的所有符號存儲在此處。在任何異常的情況下,捕獲的區塊信息將被保持在幀數據中;
(4) PC寄存器(PC Registers):每個線程都有單獨的PC寄存器,用于保存當前執行指令的地址。一旦執行指令,PC寄存器將被下一條指令更新;
(5) 本地方法堆棧(Native Method stacks):本地方法堆棧保存本地方法信息。對于每個線程,將創建一個單獨的本地方法堆棧。
3 執行引擎
分配給運行時數據區的字節碼將由執行引擎執行,執行引擎讀取字節碼并逐個執行。
(1) 解釋器:解釋器更快地解釋字節碼,但執行緩慢。解釋器的缺點是當一個方法被調用多次時,每次都需要一個新的解釋;
(2) JIT編譯器:JIT編譯器消除了解釋器的缺點。執行引擎將在轉換字節碼時使用解釋器的幫助,但是當它發現重復的代碼時,將使用JIT編譯器,它編譯整個字節碼并將其更改為本地代碼。這個本地代碼將直接用于重復的方法調用,這提高了系統的性能。JIT的構成組件為:
- 中間代碼生成器(Intermediate Code Generator):生成中間代碼
- 代碼優化器(Code Optimizer):負責優化上面生成的中間代碼
- 目標代碼生成器(Target Code Generator):負責生成機器代碼或本地代碼
- 分析器(Profiler):一個特殊組件,負責查找熱點,即該方法是否被多次調用;
(3) 垃圾收集器(Garbage Collector):收集和刪除未引用的對象。可以通過調用“System.gc()”觸發垃圾收集,但不能保證執行。JVM的垃圾回收對象是已創建的對象。
Java本機接口(JNI):JNI將與本機方法庫進行交互,并提供執行引擎所需的本機庫。
本地方法庫(Native Method Libraries):它是執行引擎所需的本機庫的集合。
來自:http://www.androidchina.net/6231.html