深入理解Java虚拟机之栈帧

1,685 阅读3分钟

概念

栈帧是用来存储数据和部分过程结果的数据结构,同时也被用来处理动态链接、方法返回值和异常分派。

生命周期

栈帧随着方法的调用而创建,随着方法结束而销毁。

存储内容

栈帧的存储空间分配在Java虚拟机栈,每个栈帧包含局部变量表操作数栈以及指向当前方法所属类的运行时常量池的引用

内存大小

局部变量表和操作数栈的容量在编译期确定,并通过方法的code属性保存并提供给栈帧使用,因此栈帧的容量仅取决于Java虚拟机的实现和方法调用时可被分配的内存。

局部变量表

局部变量表是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量。

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

虚拟机通过索引定位的方式使用局部变量表。

在方法执行时,虚拟机是使用局部变量表完成参数值到参数变量列表的传递过程。如果是实例方法(非static的方法),那么局部变量表中第0位索引的Slot默认是用于传递方法所属对象实例的引用。

局部变量表中的slot是可重用的。

操作数栈

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

在任意时刻,操作数栈都会有一个确定的栈深度,long/double类型的数据占两个单位栈深度,其他数据类型会占用一个单位栈深度。

动态链接

每个栈帧内部都包含一个指向运行时常量池的引用来支持当前方法的代码实现动态链接。Java类会被虚拟机编译成Class文件,在编译时,Java类并不知道所引用的类的实际地址,因此只能使用符号引用来代替,动态链接的作用就是将这些符号引用所表示的方法转化为实际方法的直接引用。

方法返回地址

方法返回分为两种:正常调用完成返回、异常返回。

如果读完觉得有收获的话,欢迎点赞、关注、加公众号【Java在线】,查阅更多精彩历史!!!