虚拟机栈的栈帧都包含些什么?

一、虚拟机执行引擎

虚拟机执行引擎是java虚拟机核心组成部分之一。虚拟机是相对于物理机的概念,他们都有代码执行能力,区别在于物理机执行引擎直接建立在处理器、硬件指令集、操作系统层面,而虚拟机的执行引擎是由自己实现,用于执行虚拟机字节码指令集。
执行引擎执行java代码的时候可能有解释执行(通过解释器执行)和编译执行(通过执行编译器产生本地代码执行)两种方式,所有的java虚拟机执行引擎都是一致的,输入的是字节码文件,处理过程是字节码解析的等效过程,输出执行结果。

二、运行时栈帧结构

栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,它是虚拟街运行时数据区中的虚拟机栈的栈元素。栈帧存储了方法的局部变量表操作数栈动态链接方法返回地址等信息。每一个方法从调用开始到执行完成的过程,都是一个栈帧在虚拟机栈里面从出栈到入栈的过程。
关于栈帧:
栈帧中主要空间的局部变量表和操作数栈,而局部变量表和操作数栈的大小,在编译期间就已经确定,不会收到运行期间变量数据的影响。
在活动线程中,只用位于栈顶的栈帧是有效的,也就是处于执行状态,成为当前栈帧。
下面看看栈帧中的各个存储空间都有什么用处。

1、局部变量表

局部变量表是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量
局部变量表有以下特征:

  • 局部变量表的容量以变量槽(Slot)为最小单位,每个Slot都应该至少能存放一个boolean、byte、char、short、int、float、reference类型的数据。
  • reference数据类型称为引用类型,虚拟机可以通过此类型数据直接或间接地查找对象实例数据在java堆中的索引和对象所对应类在方法区中的类型信息。
  • 方法内部定义的变量存放在局部变量表中,称为局部变量。局部变量不像类变量那样有加载过程中有准备阶段,所有局部变量不会被被赋予默认初始值,必须手动赋值。

2、操作数栈

操作数栈也成为操作栈,后入先出,操作数栈的最大深度也在编译的时候就已经确定,不会在运行期间动态变化。32位数据类型所占的栈容量为1,64位数据类型所占栈容量为2.
方法在执行过程中,各种字节码指令往操作数栈中写入或提取内容,也就是入栈和出栈。比如执行iadd指令时,将操作数栈顶的两个int型数值出栈并相加,然后将结果入栈。
java虚拟机的解释执行引擎就是基于操作数栈的执行引擎。

3、动态连接

class文件的常量池中有大量的符号引用,字节码中的方法调用指令就以常量池指向的方法的符号引用作为参数。这些符号引用一部分会在类加载阶段(解析阶段)或者第一次使用的时候就转化为直接引用,这种转化成为静态解析,另一部分在没一次运行期间转化为直接引用,这部分成为动态连接。

4、方法返回地址

一个方法在执行时,只有两种方式退出这个方法:正常完成出口和异常完成出口。

  • 正常完成出口:执行引擎遇到一个方法返回的字节码指令,这时候执行引擎读取栈帧中的方法返回地址,将返回值传递给上层的方法调用者。
  • 异常完成出口:在方法执行过程中遇到了异常,并且这个异常没有在方法体内得到处理,也就是在本地异常表内没有搜索到匹配的异常处理器,就会导致方法退出。这时候执行引擎不会读取方法返回地址而直接停止执行,上层调用者不会得到任何返回值。

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

一般把动态连接、方法返回地址和其他附加信息全部归为一类,成为栈帧信息。

发布了43 篇原创文章 · 获赞 17 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/weixin_41172473/article/details/87817967
今日推荐