《Java虚拟机规范》-栈帧

**用来存储数据和部分过程结果**的数据结构, **分配在Java虚拟机栈中**,同时也被用来处理动态链接、方法返回值和异常分派。

**栈帧随方法调用创建,方法结束(包括异常结束)而销毁。**

**每个栈帧包括:局部变量表、操作数栈和指向当前方法所属类的运行时常量池的引用。**

局部变量表和操作数栈的容量在编译器确定(通过方法的Code属性保存及提供给栈帧使用),因此栈帧大小仅取决于虚拟机的实现和方法调用时可被分派的内存

一个线程中,仅正在执行的方法的栈帧是活动的 ->  **当前栈帧**(当前方法、当前类)

对局部变量表和操作数栈的操作通常都是指当前栈帧的。

**注:栈帧是线程本地    私有的数据,不可能在一个方法的栈帧中引用另一条线程的栈帧**

1. 局部变量表

**变量列表**,一个局部变量可保存一个类型为boolean、byte、char、short、float、reference和returnAddress的数据,两个局部变量可保存一个类型为long和double的数据。

局部变量通过索引访问,0 - (n-1)

long和double占用两个连续的局部变量,根据两个局部变量中索引值较小的索引值来访问(如k和k+1存储一个double,k+1的局部变量无法直接读取,但可能被写入,将导致局部变量k的内容失效)

**Java虚拟机用局部变量表完成方法调用时参数的传递**

当一个方法被调用时,它的参数将会传递至(从调用它的方法)从0开始的连续的局部变量表(即被调用方法的栈帧中的局部变量表)位置上。

当一个实例方法被调用(对象实例的方法调用,如A a = new A();a.b();)时,第一个局部变量一定用来存储被调用的方法所属对象实力的引用(即Java中的“this”),后续的其他参数将会传递至从 1 开始的连续的局部变量表位置上。

2. 操作数栈

栈帧刚被创建时,操作数栈是空的。

Java虚拟机提供一些字节码指令来从局部变量表或者对象实例的字段中复制常量或变量值到操作数栈中,也提供了一些指令用于
从操作数栈取走数据、操作数据和把操作结果重新入栈。在方法调用的时候,操作数栈也用来准备
调用方法的参数以及接收方法返回结果。

例:算数运算

表达式:a * b 、 6 *(5+(2+3)*8+3)

中缀表达式:a * b 、 6 *(5+(2+3)*8+3)

后缀表达式:a b * 、 6 5 2 3 + 8 * + 3 + *

**后缀表达式的计算原理**:当见到一个数时就把他推入栈中;在遇到一个操作符时该操作符就作用于从该栈弹出的两个数上,将所得结果推入栈中。



**中缀表达式转后(前)缀表达式:https://www.cnblogs.com/zxcjj/p/7793329.html**

**注:对操作数栈进行的操作必须与操作数栈栈顶的数据类型相匹配。有一小部分 Java 虚
拟机指令(例如 dup 和 swap 指令)可以不关注操作数的具体数据类型,把所有在运行时数据区中的数据当作裸类型(Raw Type)数据来操作 **,这些指令不可以用来修改数据,也不可以拆散那些原本不可拆分的数据,这些**操作的正确性将会通过 Class 文件的校验过程来强制保障。 **

一个 long 或者 double 类型的数据会占用两个单位的栈深度,其他数据类型则会占用一个单位深度。

3. 动态链接

每个栈帧内部都包含一个指向运行时常量池的引用,来支持当前方法的代码实现动态链接。

在 Class 文件里面,描述一个方法调用了其他方法,或者访问其成员变量是通过符号引用(Symbolic Reference,如a.b())来表示的, **动态链接的作用就是将这些符号引用所表示的方法转换为实际方法的直接引用**

类加载的过程中将要解析尚未被解析的符号引用,并且将变量访问转化为访问这些变量的存储结构所在的运行时内存位置的正确偏移量。

4. 方法正常调用完成

指方法执行过程中,无任何异常抛出-包括直接从Java虚拟机中抛出的异常和在执行时通过 throw 语句显式抛出的异常。

方法正常完成发生在一个方法执行过程中遇到了方法返回的字节码指令的时候,使用哪种返回指令取决于方法返回值的数据类型(如果有返回值的话)

在这种场景下,当前栈帧承担着回复调用者状态的责任,其状态包括调用者的局部变量表、操作数栈和被正确增加过来表示执行了该方法调用指令的程序计数器等。使得调用者的代
码能在被调用的方法返回并且返回值被推入调用者栈帧的操作数栈后继续正常地执行。

5. 方法异常调用完成

指在方法的执行过程中,某些指令导致了 Java 虚拟机抛出异常,并且虚拟机抛出的异常在该方法中没有办法处理,或者在执行过程中遇到了 athrow字节码指令显式地抛出异常,并且在该方法内部没有把异常捕获住。如果方法异常调用完成,那一定不会有方法返回值返回给它的调用者。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值