JVM 的内存模型
JVM 的内存模型(Java 虚拟机内存结构)主要分为以下几个核心区域,每个区域承担不同的职责:
程序计数器(Program Counter Register)
- 作用:记录当前线程执行的字节码指令地址(行号),确保线程切换后能恢复到正确执行位置。
- 特点:
- 线程私有,无内存溢出风险。
- 唯一在 JVM 规范中未规定
OutOfMemoryError
的区域。
Java 虚拟机栈(JVM Stack)
- 作用:存储方法的调用栈帧(局部变量表、操作数栈、动态链接、方法出口等),每个方法对应一个栈帧。
- 特点:
- 线程私有。
- 可能抛出两种错误:
StackOverflowError
:栈深度超过限制(如无限递归)。OutOfMemoryError
:栈扩展失败(如线程过多)。
本地方法栈(Native Method Stack)
- 作用:为 JVM 调用 Native 方法(如 C/C++ 实现)提供内存空间。
- 特点:与虚拟机栈类似,但服务于 Native 方法。
堆(Heap)
- 作用:存储对象实例和数组(所有线程共享)。
- 特点:
- 垃圾回收的主要区域。
- 可进一步划分为新生代(Eden、Survivor 区)和老年代。
- 可能抛出
OutOfMemoryError
(如对象过多无法回收)。
方法区(Method Area)
- 作用:存储类信息、常量、静态变量、即时编译器代码等。
- 实现变化:
- JDK 8 之前:称为“永久代”(PermGen),受 JVM 内存限制。
- JDK 8+:由“元空间(Metaspace)”替代,使用本地内存(默认无上限,可配置)。
- **可能抛出 **
OutOfMemoryError
(如加载过多类)。
运行时常量池(Runtime Constant Pool)
- 归属:方法区的一部分。
- 作用:存储类文件中的常量(字面量、符号引用)。
- 特点:支持动态性(如
String.intern()
方法)。
直接内存(Direct Memory)
- 作用:通过 NIO 的
DirectByteBuffer
分配堆外内存(如文件读写缓冲),避免 JVM 堆与 Native 堆间数据拷贝。 - 特点:
- 受本机物理内存限制。
- 可能抛出
OutOfMemoryError
。
常见问题区分
- Java 内存模型(JMM):与并发编程相关,定义线程如何通过主内存和工作内存交互。
- JVM 内存结构:本文所述内容,描述 JVM 运行时数据区的物理划分。
通过理解这些区域的功能和特点,可以更好地优化程序性能,诊断内存溢出或泄漏等问题。