JVM虚拟机栈之操作数栈

上图时JVM虚拟机栈的栈帧的内部结构,本篇主要讲解操作数栈 

一、概念:

(1)操作数栈,主要用于保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间。

(2)操作数栈就是JVM执行引擎的一个工作区,当一个方法刚开始执行的时候,一个新的栈帧也会随之被创建出来,这个方法的操作数栈是空的。(操作数栈的实现是一个数组,当数组被创建出来的时候,它的长度已经确定,只不过操作数栈不能用索引来获取数据,它是一个栈结构,只有出栈和入栈操作).

(3)每一个操作数栈都会拥有一个明确的栈帧深度用来存储数值,其所需的最大深度在编译期就定义好了,保存在方法的code属性中,为max_stack的值。

如图:

javap 命令反编译后,stack=2 是操作数栈的最大栈深度,locals=3 是局部变量的长度。

和局部变量表一样在编译期间就可以确定长度。

(4)栈中的任何一个元素都是可以任意的java数据类型。

        32bit的类型占用一个栈单位深度。

        64bit的类型占用两个栈单位深度。

(5)操作数栈并非采用范文索引的方式来进行数据访问的,而是只能通过标准的入栈(push)和出栈(pop)操作来完成一次数据的访问。

  (6) 如果被调用的方法带有返回值的化,其返回值将会被压入当前栈帧的操作数栈中,并更新pc寄存器中下一条需要执行的字节码指令。

如图:

使用jclasslib 分析:

将int类型数据返回,getsum()栈帧出栈,

发下testGetSum当前栈帧,一上来就获取上一个栈帧的返回值,并保存在操作数栈中。

补充:我们所说的java虚拟机的解释引擎是基于栈的执行引擎,其中的栈指的就是操作数栈。

二、举例更加深入的了解操作数栈:

(1)编写代码:

都以int来保存,是以int保存到局部变量表中。并不是以int类型保存到操作数栈的入栈,还是以byte类型的操作数栈入栈。

(2)反编译后的字节码指令是:

(3)刚执行这个方法,虚拟机栈就会创建栈帧:

此时pc寄存器的值是0,局部变量表和操作数栈都是空的,但它们的长度已经确定。(操作数栈那个15可以忽略)

(4)然后执行引擎根据pc寄存器的值去执行操作指令:bipush

将15 存储到操作数栈中。

(5)执行引擎根据pc寄存器的值去执行操作指令istore_1

操作数栈的15 出栈,存入到局部变量表索引为1的slot中(因为索引为0的slot中存放的是this的引用)

(6)执行引擎根据pc寄存器的值去执行操作指令bipush

将8存放到操作数栈中。

(7)执行引擎根据pc寄存器的值去执行操作指令istore_2,将操作数栈中的8出栈,存放到局部变量表索引为2的slot中

(8)执行引擎根据pc寄存器的值去执行操作指令iload_1,

将局部变量表中索引为1的数值入栈到操作数栈中

(9)执行引擎根据pc寄存器的值去执行操作指令iload_2

将局部变量表中索引为2的数值入栈到操作数栈中。

(10)执行引擎根据pc寄存器的值去执行操作指令iadd,执行引擎执行指令,通过解释器解析成机器指令,调用cpu,将8和15依次出栈,将13入栈到操作数栈中。

(11)执行引擎根据pc寄存器的值去执行操作指令istore_3

将操作数栈中的23出栈,存储到局部变量表所以为3的slot中。

(12)执行引擎根据pc寄存器的值去执行操作指令return,栈帧出栈。

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值