当前位置: 首页 > article >正文

JVM的栈里面存的是栈帧,栈帧里面存的是什么?

JVM 栈帧(Stack Frame)—— 更完整的解释

栈帧(Stack Frame)是 JVM 方法执行时的 最小单位,每个方法被调用时,JVM 都会在**虚拟机栈(JVM Stack)**中创建一个栈帧。

当方法执行完成后,栈帧出栈,方法调用结束。

📌 一个栈帧的结构(完整)

栈帧组件作用
局部变量表(Local Variable Table)存放方法的参数局部变量(基本类型、对象引用、returnAddress)
操作数栈(Operand Stack)执行方法的操作数 存取,JVM 指令从这里取数、计算、存结果
动态链接(Dynamic Linking)维护常量池 中的符号引用到实际方法、字段的解析(指向方法区中的方法)
返回地址(Return Address)记录当前方法调用者的地址(方法返回时,继续执行调用者的指令)
附加信息(Additional Info)存放异常处理表、JIT 编译优化信息等

📌 更详细的解析

1. 局部变量表(Local Variable Table)

  • 作用:存放方法中的 参数局部变量,按索引访问。
  • 存储内容
    • 基本数据类型(int、long、float、double、byte、short、char、boolean)。
    • 对象引用(指向堆中的对象)。
    • returnAddress(用于 jsr/ret 指令,主要用于 finally 处理)。
  • 索引规则
    • 参数 按顺序放入索引 0 开始的槽位。
    • static 方法的 第 0 号槽位是 this
    • longdouble 类型占两个槽位(64 位)。

示例:方法的局部变量表

public void test(int a, long b) {
    int c = a + 10;
    double d = b * 2.0;
}

局部变量表布局:

索引变量类型
0thistest 实例
1aint
2blong(占用索引 2 和 3)
4cint
5ddouble(占用索引 5 和 6)

2. 操作数栈(Operand Stack)

  • 作用:执行方法的 中间计算(比如加法、对象调用方法)。
  • 执行方式
    • JVM 是基于栈的解释器,指令从 操作数栈 取数 → 计算 → 结果入栈。
    • 每个方法的操作数栈大小在编译期就确定(字节码 max_stack 指定)。

示例:简单的字节码

public int add(int x, int y) {
    return x + y;
}

对应的 Java 字节码(javap -c

0: iload_1   // x 入操作数栈
1: iload_2   // y 入操作数栈
2: iadd      // x + y(操作数栈出两个数,相加,结果入栈)
3: ireturn   // 返回操作数栈顶部的值

执行过程(操作数栈变化):

指令操作数栈
iload_1[x]
iload_2[x, y]
iadd[x + y]
ireturn返回 x + y

3. 动态链接(Dynamic Linking)

  • 作用:在运行时 解析 常量池中的方法/字段符号引用,指向实际方法/字段
  • 两种链接方式
    • 静态解析(Static Resolution):编译时确定的方法调用(final 方法、private 方法、static 方法)。
    • 动态链接(Dynamic Linking):运行时动态绑定,比如 多态方法调用

示例:多态方法调用

class Parent { void say() { System.out.println("Parent"); } }
class Child extends Parent { void say() { System.out.println("Child"); } }

public class Test {
    public static void main(String[] args) {
        Parent obj = new Child();
        obj.say();  // 调用的是 Child 的 say() 方法
    }
}

对应的 JVM 指令

invokevirtual #2 // #2 是 "say()" 方法的符号引用

执行过程:

  1. 动态链接解析,找到 Child 类的 say() 方法(因为 obj 实际是 Child)。
  2. 方法调用

4. 返回地址(Return Address)

  • 作用:方法执行完后,返回调用者的下一条指令(方法调用后要恢复原来的执行流)。
  • 不同情况
    • 正常返回(直接回到调用者的下一条指令)。
    • 异常返回(查找异常处理表,异常未捕获则终止)。

示例

public void methodA() {
    methodB(); // 执行 methodB
    System.out.println("A"); // methodB 执行完后,返回到这里
}
public void methodB() {
    System.out.println("B");
}

返回地址作用:

方法执行
methodA先调用 methodB()
methodB执行 println("B"),然后返回 methodA
methodA执行 println("A")

总结

栈帧部分作用
局部变量表存参数、局部变量
操作数栈计算数据存取
动态链接解析方法符号引用
返回地址记录调用者的返回位置
附加信息存异常处理表等

栈帧是 JVM 运行时方法调用的核心,每个方法执行时都会创建栈帧,执行完后出栈。JVM 通过栈帧管理方法调用,支持递归、方法链调用、异常处理等功能。


一句话总结

栈帧是 JVM 运行时调用方法的基本单位,每个方法调用都会创建栈帧,存储局部变量、操作数栈、动态链接信息、返回地址等内容,方法执行完毕后栈帧出栈,恢复调用者的执行。


http://www.kler.cn/a/542467.html

相关文章:

  • SpringBootWeb三层架构分层解耦
  • 【知识科普】CPU,GPN,NPU知识普及
  • 如何评估云原生GenAI应用开发中的安全风险(下)
  • unity学习34:角色相关3,触发器trigger,铰链 hingejoint 等 spring joint, fixed joint
  • 【JVM详解二】常量池
  • 软件模拟I2C案例(寄存器实现)
  • Unity底层C#处理机制深度解析
  • eBPF入门教程(Ubuntu 24.04)
  • JavaScript设计模式 -- 工厂模式
  • 五、OSG学习笔记-矩阵变换
  • 25考研材料复试面试常见核心问题真题汇总,材料考研复试面试有哪些经典问题?材料考研复试过程最看重什么内容?
  • python C# 内存共享互传 图像 以及字符串
  • 蓝桥杯 Java B 组 - 第 1 周复习总结
  • 3、k8s项目的生命周期和yaml文件
  • uniapp商城之登录模块
  • 《深度学习》——CNN卷积神经网络模型及项目实例
  • 【Prometheus】MySQL主从搭建,以及如何通过prometheus监控MySQL运行状态
  • FTP(File Transfer Protocol)-文件传输协议
  • C++引用深度详解
  • Unity做2D小游戏5------多个动画互相转换
  • docker配置国内源
  • 【unity实战】实现摄像机跟随效果
  • 【AI知识点】大模型开源的各种级别和 deepseek 的开源级别
  • Java 大视界 -- 5G 与 Java 大数据融合的行业应用与发展趋势(82)
  • ArcGIS Pro SDK (二十六)自定义配置
  • 基于 PyTorch 的树叶分类任务:从数据准备到模型训练与测试