每個Java開發人員都知道字節碼將由JRE (Java運行時環境)運行。但是許多人不知道JRE是Java虛擬機(JVM)的實現,它分析字節碼、解釋並執行代碼。作為開發人員,清楚瞭解JVM的體系結構非常重要,因為它能讓我們更有效地編寫代碼。在本文中,我們將更深入地瞭解Java中的JVM架構以及JVM中的各種組件。
什麼是JVM?
虛擬機是物理機器的軟件實現。Java是用WORA(Write Once Run Anywhere)的概念開發的,它在虛擬機上運行。編譯器將Java文件編譯成Java .class文件,然後將那個.class文件輸入到JVM中,JVM會加載並執行類文件。
下面是JVM的架構圖。
JVM 架構圖
JVM 是如何工作的?
正如上面的架構圖所示,JVM被劃分為三個主要的子系統:
- 類裝載子系統(Class Loader Subsystem)
- 運行時數據區(Runtime Data Area)
- 執行引擎(Execution Engine)
1. 類裝載子系統
Java的動態類裝載功能由類裝載子系統來實現。它可以裝載,鏈接,還有當它在運行時(而不是編譯時)第一次引用類時,進行初始化類文件。
1.1 裝載
這個組件功能是加載類。總共有三種類裝載器:Boot Strap class Loader, Extension class Loader, 和 Application class Loader。
- Boot Strap ClassLoader – 負責從 bootstrap classpath加載類,在基礎類庫rt.jar中,具有最高的優先級類裝載器。
- Extension ClassLoader – 負責加載ext文件夾(jre\lib)中的類。
- Application ClassLoader –負責加載應用程序級類Class Path、Path和環境變量等。
上面的類加載器在加載類文件時,將遵循 Delegation Hierarchy Algorithm 算法。
1.2 鏈接Linking
- 驗證Verify – 字節碼驗證器將驗證生成的字節碼是否正確,如果驗證失敗,我們將得到驗證錯誤。
- 準備Prepare – 對於所有靜態變量,內存將被分配並分配默認值。
- 解析Resolve – 所有符號內存引用都替換為來自方法區域的原始引用。
1.3 初始化Initialization
這是類裝載的最後一個階段,在這裡所有靜態變量都將被賦與原始值,靜態代碼塊將被執行。
2. Runtime Data Area
運行時數據區域分為5個主要部分:
- 方法區域(Method Area) –所有的類級別數據都將存儲在這裡,包括靜態變量。每個JVM只有一個共享的方法區域。
- 堆區域 (Heap Area) –所有對象及其對應的實例變量和數組都將存儲在這裡。每個JVM也只有一個堆區域。由於方法和堆區域為多個線程共享內存,所以堆區存儲的數據並不是線程安全的。
- 棧區域(Stack Area) – 對於每個線程,將創建一個單獨的運行時棧。對於每個方法調用,將在堆棧內存中創建一個條目,稱為堆棧幀(Stack Frame)。所有本地變量都將在棧內存中創建。棧區域是線程安全的,因為它不是共享資源。
堆棧框架分為三個子實體:
- 局部變量數組(Local Variable Array) – 與方法相關的局部變量以及相應的值將存儲在這裡。
- 操作數堆棧(Operand stack) –如果需要執行任何中間操作,操作數堆棧作為運行時工作區來執行操作。
- Frame data – 與方法對應的所有符號都存儲在這裡。異常處理中,Catch塊信息將在框架數據中維護。
4、PC Registers – 每一個線程都有單獨的PC寄存器,在執行指令後,保存當前執行指令的地址,PC寄存器將隨下一個指令進行更新。
5、本地方法棧(Native Method stacks )–本地方法棧保存本地方法的信息。為每一個線程,將創建一個單獨的本地方法棧。
3. 執行引擎
分配給運行時數據區域的字節碼將由執行引擎執行。執行引擎讀取字節碼並逐個執行它。
- Interpreter – 解釋器解釋字節碼很快,但執行緩慢。解釋器的缺點是,當一個方法被多次調用時,每次都需要新的解釋。
- JIT Compiler – JIT編譯器消除了解釋器的缺點。執行引擎將使用解釋器的幫助來轉換字節代碼,但是當它發現重複的代碼時,它使用JIT編譯器,它編譯整個字節碼並將其更改為本機代碼。這種本機代碼將直接用於重複的方法調用,從而提高系統的性能。
- Intermediate Code generator – 生成中間代碼
- Code Optimizer – 負責優化上面生成的中間代碼
- Target Code Generator – 負責生成機器代碼或本機代碼
- Profiler – 一種特殊的組件,負責查找hotspots,即該方法是否被多次調用。
- 垃圾回收:收集和刪除未引用的對象。可以通過調用“System.gc()”來觸發垃圾收集,但不會立即執行(執行時機由GC決定)。JVM的垃圾回收收集已創建的對象。
Java Native Interface (JNI): JNI將與本地的方法庫交互併為執行引擎提供所需的本地庫。
Native Method Libraries:它是執行引擎所需的本地庫的集合。
閱讀更多 程序你好 的文章