JAVA操作码相关指令介绍(1)

之前的文章就简单的给大家介绍了各种锁的介绍与使用(文末有对应的链接),目前这章为之后讲解锁的操作底层实现先奠定下基础。

JAVA基本类型转换

JAVA中基本类型的转换是不涉及操作数的,转换的值是直接从栈顶端获得,JAVA虚拟机从栈顶弹出一个值,对他进行转换,然后再把转换结果压入栈中。

1.int、long、float、double 类型之间的相互转换

操作码 操作数 备注
i2l 将int类型的值转换为long类类型
i2f 将int类型的值转换为float类类型
i2d 将int类型的值转换为double类类型
l2i 将long类型的值转换为int类类型
l2f 将long类型的值转换为float类类型
l2d 将long类型的值转换为double类类型
f2i 将float类型的值转换为int类类型
f2l 将float类型的值转换为long类类型
f2d 将float类型的值转换为double类类型
d2i 将double类型的值转换为int类类型
d2l 将double类型的值转换为long类类型
d2f 将double类型的值转换为float类类型

2.int数据类型向byte、char、short类型的转换

操作码 操作数 备注
i2b 将int类型的值转换为byte类型值,进行带符号扩展,恢复为int类型压入栈
i2c 将int类型的值转换为char类型值,进行零扩展,恢复成int类型压入栈
i2s 将int类型的值转换为short类型值,进行带符号扩展,恢复成int类型压入栈

不存在比int类型占据更小空间的数据类型转化为int类型操作码。因为上面三种才进行压入栈的时候,就已经转换为int类型,然后再对int类型值进行运算,最后得到int类型值。

Demo:

    public static void main(String[] args) {
		byte a =2;
		byte b =1;
		byte c = (byte) (a+b);
	}
复制代码
public static void main(java.lang.String[]);
    Code:
       0: iconst_2  //常量2入栈
       1: istore_1  //弹出栈顶元素存入位置1的局部变量
       2: iconst_1  
       3: istore_2  
       4: iload_1   //取出位置1的局部变量值入栈
       5: iload_2 
       6: iadd      //加法运算
       7: i2b       //int类型转化为byte类型值
       8: istore_3  //弹出栈顶元素存入位置3的局部变量
       9: return
}
复制代码

JAVA常量操作

1.常量值隐含包含在操作码内部

操作码 操作数 备注
iconst_m1 将int类型值-1压入栈
iconst_0 将int类型值0压入栈
iconst_1 将int类型值1压入栈
iconst_2 将int类型值2压入栈
iconst_3 将int类型值3压入栈
fconst_0 将float类型值0压入栈
fconst_1 将float类型值1压入栈
fconst_2 将float类型值2压入栈
lconst_0 将long类型值0压入栈
lconst_1 将long类型值1压入栈
dconst_0 将double类型值0压入栈
dconst_1 将double类型值1压入栈
aconst_null 将空(null)对象压入栈

2.常量值在字节码中跟随操作码之后

操作码 操作数 备注
bipush 一个byte类型的数 将byte类型的数转换为int类型的数,然后压入栈
sipush 一个short类型的数 将short类型的数转换为int类型的数,然后压入栈

3.从常量池中取出常量

操作码 操作数 备注
ldc 无符号8位数indexbyte 从由indexbyte指向的常量池入口中取出一个字长的值,然后将其压入栈
ldc_w 无符号16位数indexshort 从由indexbyte指向的常量池入口中取出两个字长的值,然后将其压入栈

JAVA通用栈以及局部变量的操作

1.通用栈操作

操作码 操作数 备注 Demo
nop 不做任何操作 前:...,word
后:...,word,word
pop 从操作数栈弹出栈顶部一个字 前:...,word
后:...
pop2 从栈顶数弹出最顶端的两个字
swap 交换栈顶部的两个字 前:...,word2,word1
后:...,word1,word2
dup 复制栈顶部的一个字
dup2 复制栈顶部的两个字
dup2 复制栈顶部的两个字
dup_x1 复制栈顶部的一个字,
将复制内容以及原来弹出的两
个字长的内容压入栈
前:...,word2,word1
后:...,word1,word2,word1
dup_x2 复制栈顶部的一个字,
将复制内容以及原来弹出的三
个字长的内容压入栈
前:.,word3,word2,word1
后:.,word1,word3,word2,word1
dup2_x1 复制栈顶部的两个字,
将复制内容以及原来弹出的三
个字长的内容压入栈
dup2_x2 复制栈顶部的两个字,
将复制内容以及原来弹出的四
个字长的内容压入栈

2.局部变量压入栈

1.将一个字长的局部变量压入栈

操作码 操作数 备注
iload vindex 将位置为vindex的int类型的局部变量压入栈
iload_0 将位置为0的int类型的局部变量压入栈
iload_1 将位置为1的int类型的局部变量压入栈
iload_2 将位置为2的int类型的局部变量压入栈
iload_3 将位置为3的int类型的局部变量压入栈
fload vindex 将位置为vindex的float类型的局部变量压入栈
fload_0 将位置为0的float类型的局部变量压入栈
fload_1 将位置为1的float类型的局部变量压入栈
fload_2 将位置为2的float类型的局部变量压入栈
fload_3 将位置为3的float类型的局部变量压入栈

2.将两个字长的局部变量压入栈

操作码 操作数 备注
lload vindex 将位置为vindex和(vindex+1)的long类型的局部变量压入栈
lload_0 将位置为0和1的long类型的局部变量压入栈
lload_1 将位置为1和2的long类型的局部变量压入栈
lload_2 将位置为2和3的long类型的局部变量压入栈
lload_3 将位置为3和4的long类型的局部变量压入栈
dload vindex 将位置为vindex和(vindex+1)的double类型的局部变量压入栈
dload_0 将位置为0和1的double类型的局部变量压入栈
dload_1 将位置为1和2的double类型的局部变量压入栈
dload_2 将位置为2和3的double类型的局部变量压入栈
dload_3 将位置为3和4的double类型的局部变量压入栈

3.将对象引用局部变量压入栈

操作码 操作数 备注
aload vindex 将位置为vindex的对象引用局部变量压入栈
aload_0 将位置为0的对象引用局部变量压入栈
aload_1 将位置为1的对象引用局部变量压入栈
aload_2 将位置为2的对象引用局部变量压入栈
aload_3 将位置为3的对象引用局部变量压入栈

4.弹出栈顶元素,赋值局部变量

移动一个字长的操作:

操作码 操作数 备注
istore vindex 从栈中弹出int类型值,然后存到位置为vindex的局部变量中
istore_0 从栈中弹出int类型值,然后存到位置为0的局部变量中
istore_1 从栈中弹出int类型值,然后存到位置为1的局部变量中
istore_2 从栈中弹出int类型值,然后存到位置为2的局部变量中
istore_3 从栈中弹出int类型值,然后存到位置为3的局部变量中
fstore vindex 从栈中弹出float类型值,然后存到位置为vindex的局部变量中
fstore_0 从栈中弹出float类型值,然后存到位置为0的局部变量中
fstore_1 从栈中弹出float类型值,然后存到位置为1的局部变量中
fstore_2 从栈中弹出float类型值,然后存到位置为2的局部变量中
fstore_3 从栈中弹出float类型值,然后存到位置为3的局部变量中

移动两个字长的操作:

操作码 操作数 备注
lstore vindex 从栈中弹出long类型值,然后存到位置为vindex和(vindex+1)的局部变量中
lstore_0 从栈中弹出long类型值,然后存到位置为0和1的局部变量中
lstore_1 从栈中弹出long类型值,然后存到位置为1和2的局部变量中
lstore_2 从栈中弹出long类型值,然后存到位置为2和3的局部变量中
lstore_3 从栈中弹出long类型值,然后存到位置为3和4的局部变量中
dstore vindex 从栈中弹出double类型值,然后存到位置为vindex和(vindex+1)的局部变量中
dstore_0 从栈中弹出double类型值,然后存到位置为0和1的局部变量中
dstore_1 从栈中弹出double类型值,然后存到位置为1和2的局部变量中
dstore_2 从栈中弹出double类型值,然后存到位置为2和3的局部变量中
dstore_3 从栈中弹出double类型值,然后存到位置为3和4的局部变量中

移动引用的操作: 移动两个字长的操作:

操作码 操作数 备注
astore vindex 从栈中弹出对象引用,然后存到位置为vindex的局部变量中
astore_0 从栈中弹出对象引用,然后存到位置为0的局部变量中
astore_1 从栈中弹出对象引用,然后存到位置为1的局部变量中
astore_2 从栈中弹出对象引用,然后存到位置为2的局部变量中
astore_3 从栈中弹出对象引用,然后存到位置为3的局部变量中

5.wide指令

无符号8位局部变量索引,把方法中局部变量数的限制在256以下。一条单独的wide指令可以将8位的索引再扩展8位。跳转指令并不允许直接跳转到被wide指令修改过的操作码。

操作码 操作数 备注
wide iload,index 从局部变量位置为index的地方取出int类型值,并将其压入栈
wide lload,index 从局部变量位置为index的地方取出long类型值,并将其压入栈
wide fload,index 从局部变量位置为index的地方取出float类型值,并将其压入栈
wide dload,index 从局部变量位置为index的地方取出double类型值,并将其压入栈
wide aload,index 从局部变量位置为index的地方取出对象引用,并将其压入栈
wide istore,index 从栈中弹出int类型值,将其存入位置为index的局部变量中
wide lstore,index 从栈中弹出long类型值,将其存入位置为index的局部变量中
wide lstore,index 从栈中弹出long类型值,将其存入位置为index的局部变量中
wide fstore,index 从栈中弹出float类型值,将其存入位置为index的局部变量中
wide dstore,index 从栈中弹出double类型值,将其存入位置为index的局部变量中
wide astore,index 从栈中弹出对象引用,将其存入位置为index的局部变量中

以上先介绍一部分JAVA字节码中的一些命令,接下来还有一些方法调用等等指令,下一篇文章给大家介绍下。

扫描二维码关注公众号,回复: 6590953 查看本文章

转载于:https://juejin.im/post/5d020857e51d454d1d6284fe

猜你喜欢

转载自blog.csdn.net/weixin_33946020/article/details/93176319