共计 1522 个字符,预计需要花费 4 分钟才能阅读完成。
很多 Java 工程师语法用的很,然而真的让他说说 Java 是怎么运行的,我置信他会懵逼!!!
心愿处于这个阶段的同学能够认真阅 Class 文件系列的文章,这里涵盖了 Class 文件的绝大部分内容,当你浏览并了解之后,置信你不再迷茫。
不晓得是否还记得 Code 属性,不记得的小伙伴倡议回顾一下,Code 属性中存储了明天咱们将要解说的字节码指令。
明天介绍一下字节码指令(加载和存储指令)。所谓的字节码指令就是 JVM 在运行时所须要进行的操作,字节码指令大抵分以下集中类型:
- 加载和存储指令
- 运算指令
- 类型转换指令
- 对象创立与拜访指令
- 操作数栈治理指令
- 管制转移指令
- 办法调用和返回指令
- 异样解决指令
- 同步指令
对于大部分字节码指令,都蕴含了其操作所对应的数据类型,i 对应 Integer 类型,l 代表 Long 类型,f 代表 Float 类型,d 代表 Double 类型,a 代表 Reference 类型,b 代表 byte 类型,s 代表 short 类型,c 代表 char 类型。
加载和存储指令
加载和存储指令用于将数据在栈帧的局部变量表和操作数栈中传输。
局部变量加载到操作数栈
iload,iload_<n>,lload, lload_<n>, fload, fload_<n>, dload, dload_<n>, aload, aload_<n>
<n> 其实只是助记符,比方 iload_1 意思是将局部变量表 slot 索引为 1 的 int 型元素压入操作数栈顶,iload_1 齐全等同于 iload(1)。
操作数栈加载到局部变量表
istore,istore_<n>、lstore, lstore_<n>, fstore, fstore_<n>, dstore, dstore_<n>, astore, astore_<n>。
istore_1 作用就是将操作数栈顶元素保留到局部变量表索引为 1 的地位处。
将常量压入到操作数栈
bipush,sipush,ldc,ldc_w,ldc2_w,aconst_null,iconst_m1,iconst_<n>,lconst_<l>,fconst_<f>,dconst_<d>。
这里咱们说一下 ldc、ldc_w、ldc2_w,咱们先看一下 Java8 虚拟机标准对它的定义,如下图:
图上的意思大抵是说将常量池中的一些特定类型的常量推入操作数栈顶,这些类型包含 int,float,String, Class,java.lang.invoke.MethodType, java.lang.invoke.MethodHandle。
ldc 等同于 ldc_w, ldc2_w 等同于 ldc 的特定类型的 long 和 double。
public class ClassTest {public void test() {
Class<Long> c = Long.class;
String s = "test";
int r = Integer.MAX_VALUE;
float f = Float.MAX_VALUE;
long l = Long.MAX_VALUE;
double d = Double.MAX_VALUE;
}
}
留神看红框中的局部,ldc #2,常量池中的第二项是个 Class 类型,合乎虚拟机标准的形容;在看 ldc #3,常量池中的第三项是个 String 类型,合乎虚拟机标准的形容;ldc2_w #8、ldc2_w #11,在常量池的第 8 和第 11 项别离是 Long 和 Double 型,合乎虚拟机标准。
JVM 反对的是栈式指令集,在咱们代码运行过程中,须要通过加载和存储指令来实现变量在局部变量表和操作数栈之间的传递。
本期的加载和存储指令就介绍到这,咱们下期再见!!!
我是 shysh95,心愿能够和你专一技术的路上并肩作战,做跟绝大多数人不一样的事件,离平庸更远一点,扫码关注微信公众号,更多精彩文章!!!