Java 虛擬機在執行 Java 程式的過程中,會將其管理的記憶體劃分為若干個不同的資料區域。這些區域各有專屬用途,並依據各自的生命週期規則獨立創建與銷毀資料。理解 JVM 記憶體模型是掌握 Java 效能調優與問題排查的基石。
根據《Java 虛擬機規範》,JVM 記憶體主要劃分為線程私有區域與線程共享區域兩大類:

程式計數器是一塊較小的記憶體空間,可視為當前線程所執行的字節碼行號指示器。由於 JVM 多線程是通過輪流切換線程分配 CPU 時間片來實現的,當線程被切換出去時,必須記錄下一條將要執行的指令地址,以便線程切換回來時能繼續執行。
關鍵特性:
OutOfMemoryError 的區域虛擬機棧描述的是 Java 方法執行的記憶體模型:每個方法被執行時都會創建一個棧幀,用於存儲局部變量表、操作數棧、動態連接、方法返回地址等信息。每個方法從調用到完成,對應一個棧幀在虛擬機棧中入棧到出棧的過程。


異常場景:
StackOverflowError:棧深度超過 JVM 限制(如遞歸過深)OutOfMemoryError:無法申請足夠記憶體擴展棧(如線程過多)功能與虛擬機棧類似,區別在於服務對象:虛擬機棧服務 Java 方法(字節碼),本地方法棧服務 Native 方法(C/C++ 等)。JVM 規範未強制其結構與語言,各廠商自行實現(HotSpot 將兩者合一)。
JVM 管理的最大記憶體區域,幾乎所有對象實例與數組都在這裡分配。堆是垃圾收集器管理的主要區域(GC 堆),現代收集器多採用分代收集演算法:

堆可物理不連續,只需邏輯連續。可通過 -Xms/-Xmx 設定初始/最大值。
存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等。雖稱「永久代」,但並非永不回收:主要回收目標是常量池卸載與類型卸載(條件苛刻)。JDK 8 起移除永久代,改用元空間(本地記憶體)。
屬於方法區一部分。Class 文件中的常量池在類加載後進入運行時常量池,存放字面量(字符串、final 常量)與符號引用(類/接口全限定名、字段/方法名與描述符)。符號引用在類加載階段或首次使用時解析為直接引用。
| 錯誤類型 | 成因 | 典型場景 |
|---|---|---|
OutOfMemoryError | 區域數據增長導致無法申請更多物理記憶體,或達到 JVM 參數上限 | 堆溢出、元空間溢出、直接記憶體溢出、線程過多導致棧溢出 |
StackOverflowError | 棧幀入棧深度超過 JVM 允許最大深度 | 遞歸調用無終止條件、大量方法嵌套調用 |
理解各區域職責與溢出成因,是定位線上 OOM 問題、進行 JVM 調優的前提。