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.将一个字长的局部变量压入栈
操作码操作数备注
iloadvindex将位置为vindex的int类型的局部变量压入栈
iload_0将位置为0的int类型的局部变量压入栈
iload_1将位置为1的int类型的局部变量压入栈
iload_2将位置为2的int类型的局部变量压入栈
iload_3将位置为3的int类型的局部变量压入栈
floadvindex将位置为vindex的float类型的局部变量压入栈
fload_0将位置为0的float类型的局部变量压入栈
fload_1将位置为1的float类型的局部变量压入栈
fload_2将位置为2的float类型的局部变量压入栈
fload_3将位置为3的float类型的局部变量压入栈
2.将两个字长的局部变量压入栈
操作码操作数备注
lloadvindex将位置为vindex和(vindex+1)的long类型的局部变量压入栈
lload_0将位置为0和1的long类型的局部变量压入栈
lload_1将位置为1和2的long类型的局部变量压入栈
lload_2将位置为2和3的long类型的局部变量压入栈
lload_3将位置为3和4的long类型的局部变量压入栈
dloadvindex将位置为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.将对象引用局部变量压入栈
操作码操作数备注
aloadvindex将位置为vindex的对象引用局部变量压入栈
aload_0将位置为0的对象引用局部变量压入栈
aload_1将位置为1的对象引用局部变量压入栈
aload_2将位置为2的对象引用局部变量压入栈
aload_3将位置为3的对象引用局部变量压入栈
4.弹出栈顶元素,赋值局部变量

移动一个字长的操作:

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

移动两个字长的操作:

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

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

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

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

操作码操作数备注
wideiload,index从局部变量位置为index的地方取出int类型值,并将其压入栈
widelload,index从局部变量位置为index的地方取出long类型值,并将其压入栈
widefload,index从局部变量位置为index的地方取出float类型值,并将其压入栈
widedload,index从局部变量位置为index的地方取出double类型值,并将其压入栈
wideaload,index从局部变量位置为index的地方取出对象引用,并将其压入栈
wideistore,index从栈中弹出int类型值,将其存入位置为index的局部变量中
widelstore,index从栈中弹出long类型值,将其存入位置为index的局部变量中
widelstore,index从栈中弹出long类型值,将其存入位置为index的局部变量中
widefstore,index从栈中弹出float类型值,将其存入位置为index的局部变量中
widedstore,index从栈中弹出double类型值,将其存入位置为index的局部变量中
wideastore,index从栈中弹出对象引用,将其存入位置为index的局部变量中

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值