虚拟机字节码的执行

虚拟机栈

栈帧

栈帧虚拟机栈中的每个栈帧对应着每个方法是进行方法调用和方法执行的数据结构,每一个方法从调用开始至执行完成的过程,都对应着一个栈帧在虚拟机里边从入栈到出栈的过程。

一个栈帧包含的内容(注意:这个只是概念模型,实际存储不太一样):

  1. 局部变量表:主要存储局部变量
  2. 操作栈:方法具体执行过程,如两个局部变量相加
  3. 动态连接:一个指向运行时常量池中该栈帧对应的所属方法的引用
  4. 返回地址:方法返回调用位置的地址信息
  5. 额外附加信息:这部分取决于具体虚拟机实现

1、局部变量表

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

即:编译完成后就能确定每个方法占用内存大小

局部变量表的内容以变量槽为最小单位称为Slot。
虚拟机中没有明确指定Slot的大小,只限制说明每个Slot都能存放一个boolean、byte、char、short、int、float、reference或者returnAddress类型数据。

1)、这些基本的数据类型都可以使用32位或者更小的内存来存放。

2)、reference类型是对一个对象实例的引用,虚拟机并没有明确规定这个数据的长度,但一般这个引用类型要求具有以下两点功能:

  • 此引用必须能够直接或者间接查询到对象在java堆中的地址;
  • 此引用必须能够直接或间接查询到对象所属数据类型在方法区的存储类型信息。

关于虚拟机中reference如何具体寻找到堆中对象和方法区Class对象,在java对象创建过程,对象访问定位中,有详细介绍。
目前主流的两种访问方式:使用句柄、直接指针

3)、returnAddress类型以前用来作为处理异常的返回,现在已经淘汰,由异常表代替。

虚拟机通过索引定位的方式访问局部变量表,索引值范围从0-最大Slot数量,如果是32位类型数据局,则n就表示n个Slot,如果是64位数据,则每两个Slot代表一个64位数据。对于64位数据,java虚拟机不允许采用任何方式单独访问其中一个Slot,如果遇到这种操作的字节码,虚拟机会在类加载校验阶段抛出异常。

this的存储位置:如果方法是实例方法(即非静态方法),局部变量表中第0位存储该方法所属对象实例的引用,可以用关键字this来访问这个隐含参数。

需要注意:局部变量必须要赋初值,局部变量不像类变量一样,有两次机会赋初值,一次在准备阶段,赋系统初值;另一次在初始化阶段,赋程序员定义初值。

2、操作数栈

操作数栈的每一个元素可以是任意的java数据类型,同局部变量表一样,他的最大深度也是在编译时期就已经写入到Code属性的max_stacks中。

方法的执行过程就在这个栈上,会有各种字节码指令往栈里写入和提取内容,如在做算术运算时,就是通过操作数栈来进行的,例如执行iadd时,会将栈顶两个int值出栈相加,然后再入栈。

3、动态连接

保存一个指向运行时常量池中该栈帧所属方法的引用

这个引用和方法调用过程中的动态连接有关。

4、方法返回地址

一个方法开始执行后,有两种方式返回:

1、正常完成出口:正常return返回或执行结束返回
2、异常返回:无论是java虚拟机异常,还是抛出异常,只要在本方法的异常表中没有搜索到匹配的异常处理器,就会导致方法退出。即:没有被捕捉处理的异常,就会异常返回

无论是那种返回,都需要返回到方法调用位置,程序才能继续执行。一般来说,方法正常退出时,调用者的PC计数器的值可以作为返回地址,栈帧中很可能会保存这个计数器值。而异常退出时,返回地址要通过异常处理器表来确定的,栈帧中一般不会保存这部分信息。

5、附加信息

根据不同虚拟机具体实现,添加的额外信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值