《深入拆解Java虚拟机》学习笔记 Day18 -- Java字节码1

84 阅读2分钟

前面的jit有点懵了,继续往后学吧。

操作数栈

在解释执行过程中,每当为 Java 方法分配栈桢时,Java 虚拟机往往需要开辟一块额外的空间作为操作数栈,来存放计算的操作数以及返回结果。

即执行每一条指令之前,Java 虚拟机要求该指令的操作数已被压入操作数栈中。在执行指令时,Java 虚拟机会将该指令所需的操作数弹出,并且将指令的结果重新压入栈中。

以加法指令 iadd 为例。假设在执行该指令前,栈顶的两个元素分别为 int 值 1 和 int 值 2,那么 iadd 指令将弹出这两个 int,并将求得的和 int 值 3 压入栈中。

Java 字节码中有好几条指令是直接作用在操作数栈上的。 例如 dup: 复制栈顶元素, pop:舍弃栈顶元素。

dup 指令常用于复制 new 指令所生成的未经初始化的引用。当执行 new 指令时,Java 虚拟机将指向一块已分配的、未初始化的内存的引用压入操作数栈中。

需要注意的是,dup和pop指令只能处理非 long 或者非 double 类型的值,这是因为 long 类型或者 double 类型的值,需要占据两个栈单元。

swap 指令,用于交换栈顶两个元素的值

正常情况下,操作数栈的压入弹出都是一条条指令完成的。唯一的例外情况是在抛异常时,Java 虚拟机会清除操作数栈上的所有内容,而后将异常实例压入操作数栈上。

局部变量区

Java 方法栈桢的另外一个重要组成部分则是局部变量区,字节码程序可以将计算的结果缓存在局部变量区之中。

实际上,Java 虚拟机将局部变量区当成一个数组,依次存放 this 指针(仅非静态方法),所传入的参数,以及字节码中的局部变量。

和操作数栈一样,long 类型以及 double 类型的值将占据两个单元,其余类型仅占据一个单元。

参考文章:gk.link/a/11VPp