首页  

JVM虚拟机执行引擎     所属分类 jvm 浏览量 641
方法 最基本的执行单元
栈帧 (Stack Frame)支持虚拟机进行方法调用和方法执行背后的数据结构
虚拟机运行时数据区中的虚拟机栈(VirtualMachine Stack)的栈元素


栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回地址等信息
每一个方法从调用开始至执行结束的过程
都对应着一个栈帧在虚拟机栈里面从入栈到出栈的过程

局部变量表
局部变量表(Local Variables Table)是一组变量值的存储空间,
用于存放方法参数和方法内部定义的局部变量
在Java程序编译为Class文件时
方法的Code属性的max_locals数据项中确定了该方法所需分配的局部变量表的最大容量。



一个变量槽可以存放一个32位以内的数据类型
Java中占用不超过32位存储空间的数据类型有
boolean byte char short int float reference和returnAddress这8种类型


reference类型表示对一个对象实例的引用,
虚拟机实现至少都应当能通过这个引用做到两件事情,
一是从根据引用直接或间接地查找到对象在Java堆中的数据存放的起始地址或索引
二是根据引用直接或间接地查找到对象所属数据类型在方法区中的存储的类型信息
否则将无法实现《Java语言规范》中定义的语法约定。


当一个方法被调用时,
Java虚拟机会使用局部变量表来完成参数值到参数变量列表的传递过程,即实参到形参的传递。
如果执行的是实例方法(没有被static修饰的方法)
那局部变量表中第0位索引的变量槽默认用于传递方法所属对象实例的引用,
在方法中可以通过关键字“this”来访问到这个隐含的参数



操作数栈
操作数栈(Operand Stack)也常被称为操作栈
它是一个后入先出(Last In First Out,LIFO)栈
同局部变量表一样,操作数栈的最大深度也在编译的时候被写入到Code属性的max_stacks数据项之中。

Java虚拟机的解释执行引擎被称为“基于栈的执行引擎”,里面的“栈”就是操作数栈。


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

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



方法返回地址
当一个方法开始执行后,只有两种方式退出这个方法。

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

另外一种退出方式是在方法执行的过程中遇到了异常,
并且这个异常没有在方法体内得到妥善处理。
这种退出方法的方式称为  
异常调用完成(Abrupt Method Invocation Completion)
一个方法使用异常完成出口的方式退出,不会给它的上层调用者提供任何返回值


无论采用何种退出方式,在方法退出之后,都必须返回到最初方法被调用时的位置,
程序才能继续执行,方法返回时可能需要在栈帧中保存一些信息,
用来帮助恢复它的上层主调方法的执行状态。

方法正常退出时,
主调方法的PC计数器的值就可以作为返回地址,
栈帧中很可能会保存这个计数器值。
而方法异常退出时,返回地址是要通过异常处理器表来确定的,
栈帧中就一般不会保存这部分信息

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

上一篇     下一篇
修佛必读《心经》《金刚经》《楞严经》

JVM模块化系统

Mac快速锁屏

JVM里的方法调用分派

JVM动态语言支持

深入理解java虚拟机笔记