深入理解JAVA虚拟机学习笔记17——字节码指令1(加载和存储)
一个忙碌的周末又过去了,时间不能阻止我们前进的脚步,每天进步一点点!
上一篇在方法体中,方法体被编译成了指令,我们已经初步了解了每条字节码指令占用一个字节, 大概有200余种字节码指令。
虚拟机的解释器的工作流程大致如下图伪代码所示。
对于这么多字节码命令,可以分为几个部分。
一. 加载和存储指令:用于将数据在局部变量表和操作数栈之间传输。
1、将一个局部变量加载到操作栈:iload、iload_<n>、lload、lload_<n>、fload、fload_<n>、dload、dload_<n>、aload、aload_<n>。
2、将一个数值从操作数栈存储到局部变量表:istore、istore_<n>、lstore、lstore_<n>、fstore、fstore_<n>、dstore、dstore_<n>、astore、astore_<n>。
3、将一个常量加载到操作数栈:bipush、sipush、ldc、ldc_w、ldc2_w、aconst_null、iconst_m1、iconst_<i>、lconst_<l>、fconst_<f>、dconst_<d>。
4、扩充局部变量表的访问索引的指令:wide。
下面我们通过一段代码,简单地看一下,字节码命令是什么样的,代码如下。
执行结果如下图所示,这里就只以整形为例。
0:bipush——将常量10加载到操作数栈中;可是为什么不用iconst呢?如果截图截全一些,我们就会看到这个时存的是“a”,也就是-128到127之间用的是bipush;
2:istore_1——将10存储到局部变量表;
21:ldc——将a加载到操作数栈。
26:iload_1——将局部变量表中的10加载到操作数栈。
对于这部分不知道大家有没有注意到,以各种load为例,这么多load只是首字母不同,为什么又这么多呢?
其实首字母代表的是数据类型,以i开头代表int类型,l代表long,s代表short,b代表byte,c代表char,f代表float,d代表double,a代表reference。
对于不同的指令,都会针对不同的数据类型,提供不同的指令。
如上图所示,通过使用数据类型列所代表的特殊字符替换 opcode 列的指令模板中的 T,就可以得到一个具体的字节码指令。
如果在表中指令模板与数据类型两列共同确定的格为空,则说明虚拟机不支持这种数据类型执行这项操作。
另外对于以结尾的一些命令,适用与本地变量少于4个,当超过四个的时候,需要在后面增加对应的参数。
这里就以load为例,声明四个局部变量。
喜欢文章或想一起学习的朋友可以关注我,给我点赞,我将会持续更新,有什么疑问或文中有不当之处请给我留言,真诚地希望能与大家一起交流探讨,学习进步。