1. 程式人生 > >一圖讀懂JVM架構解析

一圖讀懂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分為三個主要子系統:

  1. 類載入器子系統(Class Loader Subsystem)
  2. 執行時資料區(Runtime Data Area)
  3. 執行引擎(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):它是執行引擎所需的本機庫的集合。