JVM的內存結構是Java程序運行時內存管理的核心,不同區域有明確的職責。
一、整體劃分
包括兩大部分,分為線程私有區域(隨線程創建/銷毀,無需垃圾回收)和線程共享區域(所有線程共用,需要垃圾回收管理)。
- 線程私有區域:程序計數器、虛擬機棧、本地方法棧。 支撐線程獨立執行(如方法調用、指令跟蹤)
- 線程共享區域:堆、方法區(元空間)。 存儲對象實例、類信息等全局數據,是內存管理的核心區域。
二、各區域詳解:
1.程序計數器(Program Counter Register):
- 線程私有: 每個線程都有獨立的程序計數器,互不干擾。
- 作用:記錄當當前線程 “下一條要執行的 JVM 字節碼指令的地址”,為線程提供執行路標,確保線程在切換(如CPU調度被中斷)后能夠恢復到正確的執行位置。
若執行的是 Java 方法,計數器存儲下一條要執行的字節碼指令的地址;
若執行的是 Native 方法(本地方法,如 C/C++ 實現),計數器值為undefined。 因為Native方法的執行由操作系統控制,而非JVM,無需JVM記錄指令地址。
特點:
1.內存空間極小,幾乎不占用資源。
2.是JVM中唯一不會發生OutOfMemoryError(OOM) 的區域。
3.本質是線程執行的路標,確保線程切換(如CPU調度)后能恢復到正確執行的位置。
2.虛擬機棧:
- 線程私有:每個線程創建時,會分配一個虛擬機棧,生命周期與線程一致。
- 作用:記錄方法調用的執行狀態,每個方法調用時,會創建一個棧幀,棧幀入棧;方法執行完畢,棧幀出棧。
- 棧幀包含的內容:
1.局部變量表: 存儲方法內的局部變量(如基本類型、對象引用),容量在編譯期確定;
2.操作數棧:方法執行時的臨時數據存儲區(如計算a+b時,先將a和b入棧,再執行加法);
3.動態鏈接:指向方法區中該方法的符號引用(運行時轉換為直接引用);
4.返回地址:方法執行完后,回到調用者的位置(如main方法調用func(),func()執行完需回到main的下一行)。
可能的異常:
1.StackOverflowError:線程請求的棧深度超過虛擬機允許的最大深度(如遞歸調用無終止條件);
2.OutOfMemoryError:虛擬機棧可動態擴展時,擴展失敗(如創建過多線程,棧內存總需求超過系統內存)。
3.本地方法棧:
- 線程私有:與虛擬機棧功能類似,但專門為 Native 方法(非 Java 實現的方法)服務。
- 特點:
可能拋出StackOverflowError(棧深度超限)和OutOfMemoryError(內存不足),與虛擬機棧一致。
4.堆:
- 線程共享:JVM中內存占比最大的區域,幾乎所有對象實例(包括數組)都在這里分配內存。
- 作用:存儲對象實例,是**垃圾回收(GC)**的主要工作區域。
- 結構劃分:
堆空間通常按照對象“存活時間”劃分為以下區域:- 新生代:存放新創建的對象,分為:
- Eden區(伊甸園):新對象優先分配到這里。
- Survivor 區(幸存者區):分為 From 和 To 兩個大小相等的區域,用于存放 Eden 區回收后存活的對象(每次 GC 后,存活對象在 From 和 To 之間轉移,經過多次存活后進入老年代)。
- 老年代:存放存活時間長的對象(如經過多次年輕代 GC 仍存活的對象)。
- 新生代:存放新創建的對象,分為:
特點:
1.堆的大小可通過**-Xms(初始堆大小)和-Xmx(最大堆大小)參數配置(盡可能兩者設為一致,避免動態擴展消耗性能);
2.是OOM 最常見的區域**(如創建對象過多且無法被 GC 回收,堆空間耗盡時拋出java.lang.OutOfMemoryError: Java heap space)。
5.方法區:
- 線程共享:存儲已被 JVM 加載的類信息、常量、靜態變量、即時編譯器(JIT)編譯后的代碼等數據。
- 歷史演進:
- JDK 7 及之前:方法區的實現稱為 “永久代(PermGen)”,屬于堆的一部分,大小固定(易 OOM);
- JDK 8 及之后:永久代被元空間(Metaspace) 取代,元空間不再使用堆內存,而是直接使用本地內存(Native Memory),大小受系統內存限制(更靈活)。
- 運行時常量池:
是方法區的一部分,存放編譯期生成的符號引用和字面量(如字符串常量"abc")。
三、各區域的協作關系:
Java 程序運行時,內存流轉大致如下:
1.類加載器將類信息加載到方法區(元空間);
2.主線程啟動,創建虛擬機棧,main方法的棧幀入棧;
3.執行new Object()時,在堆中創建對象實例,棧幀的局部變量表存儲該對象的引用(地址);
4.程序計數器記錄當前執行的字節碼指令地址,確保線程切換后能繼續執行;
5.方法執行完畢,棧幀出棧;對象不再被引用時,由 GC 在堆中回收。