JVM的内存模型
JVM 的内存模型(运行时数据区)是 JVM 执行 Java 程序时划分的内存区域,用于存储程序运行所需的数据。它由 线程共享区域(堆、方法区)和 线程私有区域(虚拟机栈、本地方法栈、程序计数器)组成,遵循 JSR-133 规范,确保内存管理和线程安全。
1. JVM 内存模型详解
(1) 堆(Heap)
- 作用:存储对象实例和数组,是 GC(垃圾回收)的核心区域。
- 特点:
- 线程共享,所有线程访问。
- 动态分配,JVM 启动时指定大小(如
-Xms
、-Xmx
)。 - 分区(HotSpot JVM):
- 新生代:Eden、Survivor(From、To),存放新对象。
- 老年代:存放长期存活对象。
- 示例:
Object obj = new Object(); // 分配在堆上
(2) 方法区(Method Area)
- 作用:存储类信息、常量、静态变量和 JIT 编译后的代码。
- 特点:
- 线程共享。
- JDK 7 前称“永久代”(PermGen),JDK 8 改为元空间(Metaspace),使用本地内存。
- 运行时常量池:
- 存储字面量和符号引用(如
String s = "abc"
的"abc"
)。 - 示例:
static int x = 10; // 存储在方法区
(3) 虚拟机栈(Java Virtual Machine Stack)
- 作用:线程私有,存储方法执行的栈帧(Stack Frame)。
- 栈帧内容:
- 局部变量表、操作数栈、动态链接、返回地址。
- 特点:
- 每个线程一个栈,方法调用时压栈,结束时出栈。
- 大小可调(如
-Xss
)。 - 异常:
StackOverflowError
:栈溢出。- 示例:
void method() { int a = 1; } // a 在栈中
(4) 本地方法栈(Native Method Stack)
- 作用:支持本地方法(Native Method,如 JNI 调用 C 代码)的执行。
- 特点:
- 线程私有,与虚拟机栈类似。
- 实现因 JVM 厂商而异。
- 示例:
System.arraycopy(); // 调用本地方法
(5) 程序计数器(Program Counter Register)
- 作用:记录当前线程执行的字节码指令地址。
- 特点:
- 线程私有,小块内存。
- 指向下一条指令(字节码行号)。
- 本地方法执行时为空。
- 示例:
- 执行
i++
时,PC 指向下一指令。
2. 内存模型图示
JVM 内存模型
+---------------------+
| 线程共享区域 |
| +-------+ |
| | 堆 | |
| +-------+ |
| +-------+ |
| | 方法区| |
| +-------+ |
+---------------------+
| 线程私有区域 |
| +-------+ |
| | 虚拟机栈 | |
| +-------+ |
| +-------+ |
| | 本地方法栈 | |
| +-------+ |
| +-------+ |
| | 程序计数器 | |
| +-------+ |
+---------------------+
3. 特点与作用
- 线程共享:
- 堆:对象存储,GC 管理。
- 方法区:类元数据,长期存在。
- 线程私有:
- 栈:方法执行上下文,生命周期短。
- PC:指令执行控制。
- 内存分配:
- 动态调整(如
-Xmx
设置堆大小)。 - 元空间默认无上限(
-XX:MaxMetaspaceSize
可限)。
4. 与 Java 内存模型(JMM)的区别
- JVM 内存模型:运行时数据区,物理划分。
- JMM(Java Memory Model):线程间内存可见性规范,定义主内存和工作内存交互(如
volatile
)。
延伸与面试角度
- GC 影响:
- 堆分代(新生代、老年代),Minor GC 和 Full GC。
- 内存溢出:
- 堆:
OutOfMemoryError: Java heap space
。 - 栈:
StackOverflowError
。 - 元空间:
OutOfMemoryError: Metaspace
。 - 调优参数:
-Xms
、-Xmx
:堆初始和最大。-Xss
:栈大小。-XX:MaxMetaspaceSize
:元空间上限。- 实际应用:
- Spring Boot:对象在堆,类信息在方法区。
- 面试点:
- 问“结构”时,提 5 大区域。
- 问“异常”时,提 OOM 和 SOE。
示例(内存分配)
public class Demo {
static String s = "hello"; // 方法区
public static void main(String[] args) {
int x = 10; // 虚拟机栈
Object obj = new Object(); // 堆
}
}
总结
JVM 内存模型分为堆、方法区(共享)和栈、本地方法栈、程序计数器(私有),管理对象、类信息和线程执行。面试时,可画图或提 GC 分代,展示理解深度。