目录
1.加载与存储指令概述
- 作用:加载与存储指令用于将数据从栈帧的局部变量和操作数栈之间来回传递。
- 将一个
局部变量
加载到操作数栈:xload
、xload_<n>
,其中<n>
为0-3
。 - 将一个
常量
加载到操作数栈:bipush
、sipush
、ldc
、iconst_<n>
等,其中<n>
为0-3
。 - 将一个数值从操作数栈存储到局部变量表:
xstore
、xstore_<n>
1.1.操作数栈和局部变量表复习
1.1.1 操作数栈
详细介绍可以参考另一篇博客:https://blog.csdn.net/u011069294/article/details/107106755
1.操作数栈位于栈帧中,用于存放计算的操作数和返回结果。执行每一条指令之前,操作数会被压入到操作数栈中;在执行指令时,从操作数栈中弹出所需的操作数,并且将指令的结果重新压入栈中。
例如:图中所示的计算1+2
的例子,使用的是iadd
指令,操作数栈顶的两个元素分别是1
和2
,iadd
指令将弹出这两个数,并且将求得的结果3
压入栈中。
1.1.2 局部变量表
详细介绍可以参考另一篇博客:https://blog.csdn.net/u011069294/article/details/107067408
- 局部变量表是栈帧中另一个重要的组成部分。存放的是
this
(非静态方法)、方法传入的参数、以及方法的局部变量。
long
和double
类型的变量占两个变量槽(slot
),共8
个字节,其他的变量类型都只占一个solt
。一个solt
占4
个字节。
例子:如下图所示一个绿色的方格代表一个solt
,对于foo
方法的栈帧的局部变量表中存储的依次是this
变量、l
(占两个solt
)变量、f
变量、i
变量s
变量(存在solt
复用的情况,由于i
出了大括号作用域就没用了,所以后面的s
变量可以复用i
变量的solt
)- 需要注意的一点是,在栈帧中,与性能调优相关的部分就是局部变量表。因为局部变量表中的变量是重要的垃圾回收根节点,只要被局部变量表中的数据直接或间接引用的的对象都不能被回收。
1.2 局部变量压栈指令(load
指令系列)
- 局部变量压栈指令将局部变量表中的数据压入到操作数栈中。
- 大体上可以分为
xload_<n>
和xload
两类。其中x表示的是数据类型,<n>
表示的是将局部变量表中角标为n
的局部变量压入操作数栈,n
的取值范围为0-3
,当局部变量超过了3
个的时候,就需要使用xload
。
例子:需要注意的是局部变量表中存储的是局部变量的值。只不过为了方便,这里图中写的变量的名字。
1.3 常量入栈指令(const
、push
、ldc
系列)
- 作用:将常量压入操作数栈中。分为
const
系列、push
系列和ldc
指令。 - 指令
const
系列:用于对特定的常量入栈,入栈的常量隐藏在指令本身里。例如:iconst_<i>
(i
从-1
到5
),用于将int
类型的-1
到5
压入栈中。aconst_null
这条指令,a
表示的引用类型,null
是压入栈的值。
可以发现,const
系列能够操作的数据都有一个范围,如果需要操作这个范围以外的数据怎么办?例如,iconst
操作的范围是-1
到5
,如果需要将6
压入操作数栈中怎么办? - 为了解决上面的问题,有了
push
系列的指令。push
指令分为bipush
和sipush
,分别表示的是将一个字节(b
表示byte
)的整数和两个字节(s
表示short
)的整数压入到操作数栈中。
可以发现,一个字节和两个字节,能够操作的数的范围也有限,超过这个范围怎么办? - 最终,为了解决上面的问题,又引入万能的
ldc
指令。接收一个8
位的参数,该参数指向常量池中的int
、float
或者String
类型的索引,将字符串常量池中对应的内容压入栈中。
- 各个指令能够操作的数的范围如下表所示:
例子: 代码和对应的常量入栈指令对应关系,如下图所示。可以发现,当超过iconst
能够操作的范围的时候,使用的是bipush
,超过bipush
能够操作的范围之后,使用sipush
,超过sipush
能够操作的范围之后,使用的是ldc
。
同理对于其他数据类型的常量入栈指令也是类似的。
1.4 出栈装入局部变量表指令(store
系列)
- 作用:将操作数栈中的栈顶元素弹出,装入局部变量表的指定位置,给局部变量赋值。
- 分为
xstore
和xstore_n
两种。其中x
表示的是数据类型,n
表示的是局部变量表索引位置。xstore
需要带一个byte
类型的参数,指明局部变量表索引位置。
例子:
总结
可以发现,除了store
是从栈中取数据放到局部变量表中。其它的命令都是从局部变量表中取数据压入栈中。
更多JVM文章请访问我的JVM专栏:
https://blog.csdn.net/u011069294/category_10113093.html