這篇文章圖文詳解JVM體系結構
JVM 是一種抽象的計算機,基於堆疊架構,它有自己的指令集和記憶體管理,是Java 跨平台的依據,JVM解釋執行字節碼,或將字節碼編譯成本地程式碼執行。 Java 虛擬機體系架構如下:
Class File 是平台無關的二進位文件,包含著能被JVM執行的字節碼,其中多字節採用大端序,字元使用一種改進的UTF-8編碼。 Class檔案精確的描述了一個類別或介面的訊息,其中包括:
類別載入器,JVM在類別首次使用時動態的載入、連結和初始化。 JVM預設的載入模型是雙親委派模型,類別載入器之間存在父子關係的層次結構,內部使用組合實作。另外還有其他的加載方式,例如Servlet加載,它先嘗試自己加載,不成功再委派上層加載器,類別隔離;OSGI加載器之間是一種網狀的依賴關係,沒有上下層的區分,比較靈活。
載入就是將Class檔案表示的類別或接口,在JVM方法區中建立一個與之對應的java.lang.Class對象,像Class.forName()、ClassLoader.loadClass()、反射都能觸發類別載入。當觸發一個類別載入時,詳細的過程如下:
檢查類別是否已經被載入
將載入請求委派給上層類別加載器
自己嘗試搜尋類別並載入
當ClassLoader在classpath中找不到類別文件,就會拋出ClassNotFoundException;當類別A引用類別B,類別A已經成功加載,但是載入B時未找到類別文件,會拋出NoClassDefFoundError。 JVM有以下幾個類別載入器:
Extension ClassLoader,擴充類別載入器,載入
#System ClassLoader,系統類別載入器,也叫應用程式程式類別載入器(Application class loader),載入CLASSPATH 環境變數中的類別
驗證:確保class檔案的正確性。
準備:為類別靜態欄位分配記憶體並初始化為預設值,不會執行任何字節碼指令。
解析:將符號引用轉為方法區(執行時間常數池)直接引用
#執行類初始化方法,即賦值靜態字段,執行靜態區塊,順序依照其定義的先後。父類別的靜態域會先於子類別靜態域初始化。
至此,一個類別或介面被載入到了記憶體中,JVM會保證整個過程是線程安全的。需要注意的是整個過程沒有涉及任何實例物件。
Method Area:執行緒共享,儲存執行時間常數池、類別欄位和方法資訊、靜態變數和方法的字節碼,是堆的邏輯組成部分,這部分的垃圾回收是可選的。值得一提的是Hotspot JVM自JDK8之後,調整了這部分內存的內容,class meta-data的分配使用本地內存,interned String和類別靜態變數移動到了Java堆。
運行時常數池:對於JVM來說具有核心作用,基本上涉及方法或字段,JVM就會在運行時常數池中搜尋其特定的記憶體位址。
Heap:線程共享,儲存實例對象,實例變數以及陣列,是垃圾回收的主要區域。
JVM Stack:執行緒私有,用於儲存堆疊幀,當方法被呼叫時會建立一個堆疊幀入棧,堆疊幀由以下幾部分組成:
局部變數表:從0開始儲存this、方法參數、局部變數。
操作數棧:方法的工作區,在操作數棧和局部變數之間交換數據,儲存中間結果,操作數棧深度在編譯時就能確定。
幀資料:方法傳回值,異常分派,以及目前方法所在類別運行時常數池的參考。
PC Register:執行緒私有,保存目前指令位址,執行後指向下一指令位址。
Native Method Stack:執行緒私有,儲存本機方法信息,C或C++堆疊。
讀取、翻譯、執行字節碼。 JVM基於棧架構,這個棧就是操作數棧,字節碼指令就是透過它進行各種運算。此外還有基於暫存器的虛擬機器。
Interpreter,翻譯:解釋字節碼比較快,執行慢,缺點是每次方法呼叫都要重新翻譯解釋一遍。
JIT Compiler,即時編譯:找出程式中頻繁呼叫的熱點方法,將字節碼編譯成本地程式碼,提高效能。
Garbage Collector,垃圾收集器:回收無效對象,判斷對像是否可回收,可採用不同的垃圾回收演算法。
JNI,呼叫本機方法,c/c++函式庫;執行引擎所需的本機方法函式庫。
主流JVM的實作有Oracle的Hotspot JVM、JRockit以及IBM的JVM。說到JVM調優,預設指的就是Hotspot VM,足見其流行程度。如今搞Java不去了解JVM就顯得有點low了-v-。
要寫出高品質程式碼,不僅要了解JVM,像調優,問題排查等都需要完備的電腦基礎知識,其實無論用什麼語言開發,都是一個建構和完善自身電腦知識體系的過程。
以上是圖文詳解JVM體系結構的詳細內容。更多資訊請關注PHP中文網其他相關文章!