这是变量值的存储空间,用于存放方法参数和方法内部定义的局部变量。 在 Java 编译成 Class 文件时,就在方法的 Code 属性的 MAX_LOCALS 数据项中确定该方法需要分配的最大局部变量表的容量。这个区域,以 Slot 为最小单位,32 位虚拟机,一个 slot 可以放 32 位(4字节)以内的数据。如果是 64 位,虚拟机就会以高位对其方式,分配两个连续的 slot 空间,相当于把一次 long 和 double 数据类型,读写分割成为两次 32 位读写。 Slot 对对象的引用会影像 GC,如果被引用,将不会被回收。
与局部变量表一样,在编译时期就确定了该方法所需要分配的局部变量表的最大容量。操作数栈的每一个元素可以是任意的 Java 数据类型。当一个方法刚执行时,这个方法的操作数栈是空的,在方法执行的过程中,会有各种字节码指令往操作数栈中写入和提取内容,也就是出栈/入栈操作。
一般来讲,栈帧之间都是独立的,但是大多虚拟机都会做优化,使局部变量表和操作数栈之间有重叠,以达到共用的目的,这样能节省额外的参数复制等工作,重叠过程类似下图。

每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,Class 文件的常量池中存有大量的符号引用。字节码中的方法调用指令就以常量池中方法的符号引用为参数。这些符号引用一部分会在类加载的时候,或者第一次使用的时候转化为直接引用(静态方法,似有方法等),这种转化成为静态解析。另一部分将在每一次运行期间转化为直接引用。这部分称之为动态连接。
当一个方法开始执行后,有以下两种方式来退出
说人话:方法返回地址主要存放调用该方法的 PC 寄存器的值(程序计数器),方法无论是通过正常还是异常退出,都应该返回该方法被调用的位置,正常退出是,调用 PC 计数器的值作为返回地址,即调用该方法的指令的下一条指令地址。如果异常退出的话,返回地址是通过异常表来确定,栈帧中一般不会保存这部分信息。这两个出口的区别就在于,异常完成出口退出是不会给上一层调用者产生任何返回值的。
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。