首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

JVM 核心基礎:記憶體結構與類加載機制深度解析

     編輯:Java 程式設計入門

Java 虛擬機(JVM)是 Java 程式執行的基石,理解其記憶體模型與類加載流程,對效能調優、問題排查至關重要。本文系統梳理 JVM 物理結構、編譯執行流程、類加載器層級、執行引擎棧幀結構,以及運行時資料區的劃分與 OOM 場景。

一、JVM 是什麼?

JVM 屏蔽了底層硬體與作業系統差異,實現「一次編寫,到處執行」。除 Java 外,Scala、Kotlin、JRuby 等語言也運行於 JVM 之上。不同平台(Windows、Linux、macOS、Android)擁有各自的 JVM 實現。

二、Java 編譯與執行流程

  1. 源碼編譯:.java → javac → .class 位元碼檔案。
  2. 類加載:類加載器將 .class 載入記憶體,經驗證、準備、解析、初始化。
  3. 執行引擎:基於棧的解釋器執行位元碼,熱點代碼經 JIT 編譯為機器碼提升效能。

2.1 類文件結構

.class 檔案主要包含三部分:

  • 結構資訊:版本號、常量池大小等。
  • 元數據:類/父類/介面聲明、字段/方法資訊、常量池。
  • 方法資訊:位元碼指令、異常表、棧幀大小、調試符號。

2.2 類加載器層級與雙親委派

雙親委派機制:檢查是否已加載時自底向上(Custom → Bootstrap);加載時自頂向下(Bootstrap → Custom),確保核心類只被加載一次,防止偽造核心類。

2.3 執行引擎與棧幀結構

JVM 採用基於棧的指令集(不同於 Android 的基於寄存器)。每個執行緒擁有獨立的程序計數器(PC)與 Java 虛擬機棧。

  • 程序計數器:指向下一條位元碼指令偏移量,執行 Native 方法時為空。
  • 棧幀:對應一次方法調用,包含局部變量表、操作數棧、動態連接、方法返回地址。

棧幀結構

局部變量表

以 Slot(32 位)為單位存放基本類型、引用、returnAddress。long/double 佔兩個 Slot。索引 0 存放 this 引用(非 static 方法),參數緊接其後,再是局部變量。Slot 可重用,影響 GC 行為。

操作數棧

32 位類型佔 1 深度,64 位佔 2。位元碼指令透過入棧/出棧完成運算。最大深度編譯期確定。

動態連接

每個棧幀持有指向運行時常量池中該方法符號引用的指標,支援動態連接(運行期解析為直接引用)。

方法返回地址

正常返回:調用者 PC 計數器值;異常返回:由異常處理表決定。

三、運行時資料區與 OOM

JVM 記憶體區域

3.1 程序計數器

線程私有,唯一無 OOM 規定的區域。

3.2 Java 虛擬機棧

線程私有,生命週期與線程同步。異常:StackOverflowError(棧深度超限)、OutOfMemoryError(動態擴展失敗,多線程下常見)。

3.3 本地方法棧

服務 Native 方法,功能類似 Java 棧。

3.4 Java 堆

所有線程共享,最大區域,幾乎所有對象實例與數組在此分配,GC 主戰場(「GC 堆」)。物理可不連續,邏輯連續。無法分配且無法擴展時拋 OutOfMemoryError。

3.5 方法區

線程共享,存放類資訊、常量、靜態變量、JIT 編譯代碼。HotSpot 稱「永久代」(JDK 8 移至 Metaspace),JRockit/IBM J9 無永久代概念。可選擇不實現 GC,主要回收廢棄常量與無用類。

運行時常量池:屬方法區一部分,具動態性,String.intern() 可將字串加入池中。

3.6 直接記憶體

非 JVM 運行時資料區,JDK 1.4 NIO 引入,通過 DirectByteBuffer 在堆外分配,避免堆與 Native 堆複製,受本機總記憶體限制,亦可能導致 OOM。

3.2 記憶體溢出與洩漏

OOM 示意

  • 棧大小與線程數權衡:OS 進程記憶體有限,扣除堆、方法區、PC、進程本身,剩餘給棧。單線程棧越大,可建線程越少。大量線程導致 OOM 時,可減小 -Xss 或堆大小換取更多線程。
  • 記憶體洩漏 vs 溢出:洩漏指分配的記憶體失去引用無法回收(Java 少見,但持有不用的引用會造成);溢出指需求超過系統上限。

3.3 對象實例化與訪問方式

Object obj = new Object();

涉及 Java 棧(引用)、Java 堆(實例)、方法區(類型資訊)。訪問方式兩種:

  1. 句柄池:引用指向穩定句柄,GC 移動對象只改句柄指針,引用不變。句柄訪問
  2. 直接指針:引用直接指向對象,速度快,HotSpot 默認採用。直接指針訪問
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
加載器職責實現語言
Bootstrap ClassLoader載入 $JAVA_HOME/jre/lib/rt.jar 核心類庫C++
Extension ClassLoader載入 jre/lib/ext/*.jar 或 -Djava.ext.dirs 指定目錄Java
App ClassLoader載入 classpath 下的類Java
Custom ClassLoader應用自定義(如 Tomcat、JBoss)Java