说一说 JVM 的内存模型
🧠 前言
JVM 内存结构(JVM Memory Structure) 和 Java 内存模型(Java Memory Model, JMM) 是两个不同的概念,但经常被混淆。
JVM 内存结构:指的是 JVM 在运行时,其内部的数据存储区域是如何划分的(如堆、栈、方法区等)。这是本文的重点。
Java 内存模型:是一种并发编程规范,它定义了多线程之间如何通过内存交互、可见性、原子性和有序性问题。
☕ JVM 内存结构(运行时数据区)
JVM 在执行 Java 程序的过程中,会把它所管理的内存划分为若干个不同的数据区域。根据《Java 虚拟机规范》,JVM 内存结构如下图所示:

1️⃣ 程序计数器(Program Counter Register)
定义:
一块较小的内存空间,记录当前线程所执行的字节码行号。
作用:
字节码解释器通过它控制代码执行顺序(顺序、跳转、异常处理等)。
多线程切换时,每个线程都依赖它恢复执行位置。
特点:
线程私有
唯一一个不会发生 OutOfMemoryError 的区域
2️⃣ Java 虚拟机栈(Java Virtual Machine Stack)
定义:
描述 Java 方法执行的内存模型,每个方法执行时都会创建一个栈帧(Stack Frame)。
栈帧结构:
局部变量表
操作数栈
动态链接
方法出口
特点:
线程私有
生命周期与线程相同
异常:
StackOverflowError:递归太深OutOfMemoryError:栈扩展时内存不足
💡 本地方法栈
与虚拟机栈作用类似,但为 Native 方法 服务。
HotSpot 虚拟机中,二者常合并实现。
3️⃣ Java 堆(Heap)

定义:
JVM 内存中最大的一块区域,存放对象实例与数组,所有线程共享。
作用:
是**垃圾收集器(GC)**管理的主要区域,也叫 GC 堆。
内部分区(分代收集理论):
新生代(Young Generation)
Eden 区
Survivor 0(From Survivor)
Survivor 1(To Survivor)
老年代(Old Generation):经历多次 GC 后仍存活的对象。
元空间(Metaspace):方法区的实现(JDK 8 起使用本地内存)。
异常:
OutOfMemoryError:对象无法分配且堆无法扩展。
4️⃣ 方法区(Method Area)
定义:
存储类信息、常量、静态变量、JIT 编译代码等。可视为“类的元数据仓库”。
特点:
线程共享
又称 “非堆(Non-Heap)”
内存不足会抛出
OutOfMemoryError
⚙️ 实现演进
5️⃣ 运行时常量池(Runtime Constant Pool)
定义:
属于方法区的一部分,用于存放字面量(Literal)和符号引用(Symbolic Reference)。
内容包括:
字面量:字符串、final 常量值
符号引用:类名、方法名、字段描述符
特点:
具备动态性,可运行时新增常量(如
String.intern())可能抛出
OutOfMemoryError
⚡ 直接内存(Direct Memory)
定义:
非 JVM 管理内存,由 java.nio 包通过本地函数库直接分配。
作用:
避免在堆和本地内存间复制,提高 I/O 性能。
通过 DirectByteBuffer 访问。
特点:
不受堆大小限制,但受物理内存约束
同样可能
OutOfMemoryError
🧩 内存区域对比表
✅ 总结
理解 JVM 内存结构的划分与特性,是搞清楚:
对象分配与回收(GC 调优)
内存泄漏与溢出定位
线程执行机制的基础。
一句话总结:
堆养对象,栈管执行,方法区存类信息,直接内存搞高性能。