欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 建筑 > JVM的栈里面存的是栈帧,栈帧里面存的是什么?

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

2025/2/11 23:24:39 来源:https://blog.csdn.net/liuruiaaa/article/details/145557108  浏览:    关键词: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(); // 执行 methodBSystem.out.println("A"); // methodB 执行完后,返回到这里
}
public void methodB() {System.out.println("B");
}

返回地址作用:

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

总结

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

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


一句话总结

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

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com