🧠 前言

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

⚙️ 实现演进

JDK 版本

方法区实现

特点

JDK 7 及之前

永久代(PermGen)

容量固定,易 OOM

JDK 8 及之后

元空间(Metaspace)

使用本地内存,更灵活,避免 PermGen OOM


5️⃣ 运行时常量池(Runtime Constant Pool)

定义:
属于方法区的一部分,用于存放字面量(Literal)和符号引用(Symbolic Reference)

内容包括:

  • 字面量:字符串、final 常量值

  • 符号引用:类名、方法名、字段描述符

特点:

  • 具备动态性,可运行时新增常量(如 String.intern()

  • 可能抛出 OutOfMemoryError


⚡ 直接内存(Direct Memory)

定义:
非 JVM 管理内存,由 java.nio 包通过本地函数库直接分配。

作用:
避免在堆和本地内存间复制,提高 I/O 性能。
通过 DirectByteBuffer 访问。

特点:

  • 不受堆大小限制,但受物理内存约束

  • 同样可能 OutOfMemoryError


🧩 内存区域对比表

区域

线程共享

存储内容

可能错误

程序计数器

当前线程执行位置

虚拟机栈

局部变量表、操作数栈

SOF / OOM

本地方法栈

Native 方法栈帧

SOF / OOM

Java 堆

对象实例、数组

OOM

方法区

类信息、常量、静态变量

OOM

运行时常量池

字面量、符号引用

OOM

直接内存

NIO 堆外缓冲区

OOM


✅ 总结

理解 JVM 内存结构的划分与特性,是搞清楚:

  • 对象分配与回收(GC 调优)

  • 内存泄漏与溢出定位

  • 线程执行机制的基础。

一句话总结:

堆养对象,栈管执行,方法区存类信息,直接内存搞高性能。