【深入理解JAVA虚拟机】读书笔记——运行时栈帧结构

学习参考资料:周志明老师的著作《深入理解Java虚拟机(第3版)》

运行时栈帧结构

栈帧存储了方法的局部变量、操作数栈、动态连接、方法返回值和一些附加信息。

每个方法从调用到结束都伴随着一个栈帧从入栈到出栈的过程。

另外,在编译Java源代码时,一个栈帧的局部变量表的大小和操作数栈的深度就已经被确定了,并且写入Class文件中方法的Code属性。

image-20211209205131474

1.局部变量表(重点)

作用

局部变量表用于存放方法参数方法内部定义的局部变量

组成

局部变量表的最小单位是变量槽,一个变量槽可以存放32位以内的数据类型,Java中占用不超过32位存储空间的数据类型有 boolean、byte、char、short、int、 float、referencereturnAddress 这8种类型,如果要存储double这种64位数据类型的话,需要两个变量槽。其中reference是指对象引用,可以间接或直接指向堆中数据存放的地址信息,或指向数据类型在方法区中的存储的类型信息。

局部变量表的第0个变量槽默认存储的是传递方法所属实例的引用

变量槽是可以复用的,也就是说一个方法的局部作用域已经执行完之后,它们的作用域可以交给其他变量使用,可以节省空间。

如果一个局部变量定义了,但是并没有给他赋值,是不能使用的,并不像类静态变量即使没有赋值也可以使用,这是因为在类加载过程中的“准备”阶段将类变量在方法区分配了空间并赋了”零“值,如下代码编译时就已经出错:(关于类加载可以看我这篇文章)

image-20211209211246716

2.操作数栈(重点)

操作数栈(Operand Stack)也常被称为操作栈,它是一个后入先出(Last In First Out,LIFO)栈。操作数栈的每一个元素都可以是包括long和double在内的任意Java数据类型。32位数据类型所占的栈容量为1,64位数据类型所占的栈容量为2。

作用

方法执行过程中,会有各种字节码指令往操作数栈中写入和提取内容

举个例子,假如整数相加的字节码指令iadd,在执行这条指令时会将栈顶的两个元素a,b出栈并相加再入栈。

这里要注意,操作数栈中元素的数据类型必须与字节码指令的序列严格匹配,在编译代码时就会验证这一点,再在类校验阶段的数据流分析中还要再次验证这一点。

3.动态连接

每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接(Dynamic Linking)。

我们知道Class文件的常量池中存有大量的符号引用,字节码中的方法调用指令就以常量池里指向方法的符号引用作为参数。这些符号引用一部分会在类加载阶段或者第一次使用的时候就被转化为直接引用,这种转化被称为静态解析。另外一部分将在每一次运行期间都转化为直接引用,这部分就称为动态连接

4.方法返回地址

当一个方法开始执行后,只有两种方式退出这个方法。第一种方式是执行引擎遇到任意一个方法返回的字节码指令,这时候可能会有返回值传递给上层的方法调用者(调用当前方法的方法称为调用者或者主调方法),方法是否有返回值以及返回值的类型将根据遇到何种方法返回指令来决定,这种退出方法的方式称为“正常调用完成”(Normal Method Invocation Completion)。

另外一种退出方式是在方法执行的过程中遇到了异常,并且这个异常没有在方法体内得到妥善处理。无论是Java虚拟机内部产生的异常,还是代码中使用athrow字节码指令产生的异常,只要在本方法的异常表中没有搜索到匹配的异常处理器,就会导致方法退出,这种退出方法的方式称为“异常调用完成(Abrupt Method Invocation Completion)”。一个方法使用异常完成出口的方式退出,是不会给它的上层调用者提供任何返回值的。

无论采用何种退出方式,在方法退出之后,都必须返回到最初方法被调用时的位置,程序才能继续执行,方法返回时可能需要在栈帧中保存一些信息,用来帮助恢复它的上层主调方法的执行状态。一般来说,方法正常退出时,主调方法的PC计数器的值就可以作为返回地址,栈帧中很可能会保存这个计数器值。而方法异常退出时,返回地址是要通过异常处理器表来确定的,栈帧中就一般不会保存这部分信息。

方法退出的过程实际上等同于把当前栈帧出栈,因此退出时可能执行的操作有:恢复上层方法的局部变量表和操作数栈,把返回值(如果有的话)压入调用者栈帧的操作数栈中,调整PC计数器的值以指向方法调用指令后面的一条指令等。

5.附加信息

《Java虚拟机规范》允许虚拟机实现增加一些规范里没有描述的信息到栈帧之中,例如与调试、性能收集相关的信息,这部分信息完全取决于具体的虚拟机实现,这里不再详述。在讨论概念时,一般会把动态连接、方法返回地址与其他附加信息全部归为一类,称为栈帧信息。


请添加图片描述

后面还会陆陆续续更新这系列的读书笔记,期待您的关注~~

おすすめ

転載: blog.csdn.net/weixin_46804107/article/details/121844668