特性 | 说明 |
---|---|
作用 | 记录当前线程执行的字节码行号指示器(分支/循环/异常处理的核心) |
线程私有 | ✅ 每个线程独立存储指令位置 |
异常 | ❌ 唯一不会抛出OutOfMemoryError 的区域 |
特殊场景 | ⚠️ 执行Native方法时值为undefined |
// 栈帧内存模型示例
public void calculate() {
int a = 1; // → 局部变量表(基本类型)
Object obj = new Object(); // → 引用存栈,对象实例在堆
obj.toString(); // → 动态链接指向方法区的方法字节码
}
虚拟机栈是JVM执行Java方法的运行时数据结构,通过栈帧为每个方法调用提供隔离的执行环境,管理局部数据存储和运算过程,构建完整的方法调用链
组件 | 作用 |
---|---|
局部变量表 | 存储基本类型(int/boolean等)和对象引用(reference指针) |
操作数栈 | 执行计算指令的临时工作区(如加减乘除) |
动态链接 | 指向运行时常量池的方法符号引用(关联方法区) |
方法出口 | 记录方法返回地址(正常return或异常退出) |
异常 | ⚠️ StackOverflowError (递归过深)⚠️ OOM (扩展栈内存失败) |
特性 | 说明 |
---|---|
作用 | 为JNI(Java Native Interface)方法提供内存空间(C/C++代码) |
线程私有 | ✅ 与虚拟机栈隔离 |
异常 | ⚠️ 同虚拟机栈(StackOverflowError/OOM) |
关键差异 | 服务Native方法而非Java方法(但HotSpot将两栈合并) |
内存比例:
-XX:NewRatio=2
:老年代:年轻代=2:1(默认)-XX:SurvivorRatio=8
:Eden:S0:S1=8:1:1对象晋升规则:
特性 | 说明 |
---|---|
线程共享 | ✅ 所有线程访问同一堆空间 |
存储内容 | 对象实例、数组、字符串常量池(JDK7+) |
GC机制 | 分代回收: - 新生代(Minor GC) - 老年代(Full GC) |
异常 | ⚠️ OutOfMemoryError (内存泄露/大对象) |
配置参数 | -Xms (初始堆大小)-Xmx (最大堆大小) |
版本 | 实现名称 | 存储位置 | 内容 | 参数配置 |
---|---|---|---|---|
JDK7- | 永久代 | JVM内存 | 类元数据/运行时常量池/静态变量 | -XX:PermSize |
JDK8+ | 元空间 | 本地内存 | 类元数据/运行时常量池 | -XX:MaxMetaspaceSize |
共性 | JIT编译代码/方法字节码 |
重大变革:
静态变量在JDK7后存入堆中!字符串常量池在JDK7从永久代移至堆。
常量池分为三级结构,关系如下:
.class
文件中的固定结构String s = "fly"; // "fly" 即字面量
✅ 符号引用:java/lang/Object
)Ljava/lang/String;
)()V
)String.intern()
)位置演变:
JDK版本 | 位置 | 原因 |
---|---|---|
JDK6 | 方法区 | 受永久代大小限制,易OOM |
JDK7+ | 堆内存 | 允许GC回收,避免OOM;调优更灵活 |
核心机制:
// 示例1:直接赋值(优先使用常量池)
String s1 = "fly"; // 在常量池创建对象
String s2 = "fly"; // 复用常量池对象(s1 == s2)
// 示例2:new创建(堆中新对象)
String s3 = new String("fly"); // 堆中创建新对象(s1 ≠ s3)
// 示例3:intern主动入池
String s4 = s3.intern(); // 返回常量池引用(s1 == s4)
设计优势:
✅ 避免重复创建:相同字符串共享内存
✅ GC可回收:JDK7+后可被垃圾回收
特性 | Class文件常量池 | 运行时常量池 | 字符串常量池 |
---|---|---|---|
存在阶段 | 编译期(.class文件) | 运行期(方法区/元空间) | 运行期(堆) |
是否可动态添加 | ❌ | ✅(intern等) | ✅(intern强制入池) |
内容 | 字面量+符号引用 | 直接引用+运行时添加的常量 | 唯一字符串的引用 |
内存回收 | 不支持 | JDK8+由元空间管理 | JDK7+支持GC回收 |
OOM风险 | 无 | 元空间溢出 | 堆内存溢出 |