上一章介绍了JAVA
一些基础类型转化以及局部变量的入栈等操作。这章继续给大家介绍下字节码命令。
JAVA数值运算
JAVA
里面提供的整数运算都基于int
和long
类型的运算。当小于int
类型的类型参与计算的时候,会将他们转化为int
类型。
1.数值之间相加
操作码 | 操作数 | 备注 |
iadd | 无 | 从栈中弹出两个int类型数,相加之后将所得int类型结果压回栈 |
ladd | 无 | 从栈中弹出两个long类型数,相加之后将所得long类型结果压回栈 |
fadd | 无 | 从栈中弹出两个float类型数,相加之后将所得float类型结果压回栈 |
dadd | 无 | 从栈中弹出两个double类型数,相加之后将所得double类型结果压回栈 |
iinc | vindex,const | 把常量与一个位于vindex位置的int类型局部变量相加 |
wide | iinc,indexconst | 把常量与一个位于vindex位置的int类型局部变量相加 |
2.数值之间相减
栈顶端的充当减数,次顶端的充当被减数
操作码 | 操作数 | 备注 |
isub | 无 | 从栈中弹出两个int类型数,相减所得int类型结果压回栈 |
lsub | 无 | 从栈中弹出两个long类型数,相减所得long类型结果压回栈 |
fsub | 无 | 从栈中弹出两个float类型数,相减所得float类型结果压回栈 |
dsub | 无 | 从栈中弹出两个double类型数,相减所得double类型结果压回栈 |
3.数值之间乘法
操作码 | 操作数 | 备注 |
imul | 无 | 从栈中弹出两个int类型数,相乘所得int类型结果压回栈 |
lmul | 无 | 从栈中弹出两个long类型数,相乘所得long类型结果压回栈 |
fmul | 无 | 从栈中弹出两个float类型数,相乘所得float类型结果压回栈 |
dmul | 无 | 从栈中弹出两个double类型数,相乘所得double类型结果压回栈 |
4.数值之间除法
次顶端的数除以顶端的数。如果整数被0除,会抛出相关异常。
操作码 | 操作数 | 备注 |
idiv | 无 | 从栈中弹出两个int类型数,相除所得int类型结果压回栈 |
ldiv | 无 | 从栈中弹出两个long类型数,相除所得long类型结果压回栈 |
fdiv | 无 | 从栈中弹出两个float类型数,相除所得float类型结果压回栈 |
ddiv | 无 | 从栈中弹出两个double类型数,相除所得double类型结果压回栈 |
5.数值之间取余
操作码 | 操作数 | 备注 |
irem | 无 | 从栈中弹出两个int类型数,取余所得int类型结果压回栈 |
lrem | 无 | 从栈中弹出两个long类型数,取余所得long类型结果压回栈 |
frem | 无 | 从栈中弹出两个float类型数,取余所得float类型结果压回栈 |
drem | 无 | 从栈中弹出两个double类型数,取余所得double类型结果压回栈 |
6.数值之间取反
操作码 | 操作数 | 备注 |
ineg | 无 | 从栈中弹出两个int类型数,取反将所得int类型结果压回栈 |
lneg | 无 | 从栈中弹出两个long类型数,取反将所得long类型结果压回栈 |
fneg | 无 | 从栈中弹出两个float类型数,取反将所得float类型结果压回栈 |
dneg | 无 | 从栈中弹出两个double类型数,取反将所得double类型结果压回栈 |
7.数值之间位移
操作码 | 操作数 | 备注 |
ishl | 无 | 将int型数值左移位指定位数并将结果压入栈顶 |
ishr | 无 | 将int型数值右(符号)移位指定位数并将结果压入栈顶 |
iushr | 无 | 将int型数值右(无符号)移位指定位数并将结果压入栈顶 |
lshl | 无 | 将long型数值左移位指定位数并将结果压入栈顶 |
lshr | 无 | 将long型数值右(符号)移位指定位数并将结果压入栈顶 |
lshr | 无 | 将long型数值右(无符号)移位指定位数并将结果压入栈顶 |
7.数值之间或
操作码 | 操作数 | 备注 |
ior | 无 | 将栈顶两int型数值作“按位或”并将结果压入栈顶 |
lor | 无 | 将栈顶两long型数值作“按位或”并将结果压入栈顶 |
8.数值之间与
操作码 | 操作数 | 备注 |
iand | 无 | 将栈顶两int型数值作“按位与”并将结果压入栈顶 |
land | 无 | 将栈顶两long型数值作“按位与”并将结果压入栈顶 |
9.数值之间异或
操作码 | 操作数 | 备注 |
ixor | 无 | 将栈顶两int型数值作“按位异或”并将结果压入栈顶 |
lxor | 无 | 将栈顶两long型数值作“按位异或”并将结果压入栈顶 |
10.数值之间比较
操作码 | 操作数 | 备注 |
dcmpg | 无 | 比较栈顶两double型数值大小,并将结果(1,0,-1)压入栈顶;当其中一个数值为NaN时,将1压入栈顶 |
dcmpl | 无 | 比较栈顶两double型数值大小,并将结果(1,0,-1)压入栈顶;当其中一个数值为NaN时,将-1压入栈顶 |
fcmpg | 无 | 比较栈顶两float型数值大小,并将结果(1,0,-1)压入栈顶;当其中一个数值为NaN时,将1压入栈顶 |
fcmpl | 无 | 比较栈顶两float型数值大小,并将结果(1,0,-1)压入栈顶;当其中一个数值为NaN时,将-1压入栈顶 |
lcmp | 无 | 比较栈顶两long型数值大小,并将结果(1,0,-1)压入栈顶 |
ifeq | 无 | 当栈顶int型数值等于0时跳转 |
ifne | 无 | 当栈顶int型数值不等于0时跳转 |
iflt | 无 | 当栈顶int型数值小于0时跳转 |
ifge | 无 | 当栈顶int型数值大于等于0时跳转 |
ifgt | 无 | 当栈顶int型数值大于0时跳转 |
ifle | 无 | 当栈顶int型数值小于等于0时跳转 |
JAVA类相关操作
1.类属性字段操作
操作码 | 操作数 | 备注 |
new | 无 | 创建类实例 |
newarray | 无 | 创建一个指定原始类型(如int,float,char…)的数组,并将其引用值压入栈顶 |
anewarray | 无 | 创建一个引用型(如类,接口,数组)的数组,并将其引用值压入栈顶 |
multianewarray | 无 | 创建指定类型和指定维度的多维数组(执行该指令时,操作栈中必须包含各维度的长度值),并将其引用值压入栈顶 |
getfield | 无 | 获取指定类的实例域,并将其值压入栈顶 |
putfield | 无 | 为指定的类的实例域赋值 |
getstatic | 无 | 获取指定类的静态域,并将其值压入栈顶 |
putstatic | 无 | 为指定的类的静态域赋值 |
2.数组操作
操作码 | 操作数 | 备注 |
baload | 无 | 将boolean或byte型数组指定索引的值推送至栈顶 |
caload | 无 | 将char型数组指定索引的值推送至栈顶 |
saload | 无 | 将short型数组指定索引的值推送至栈顶 |
iaload | 无 | 将int型数组指定索引的值推送至栈顶 |
laload | 无 | 将long型数组指定索引的值推送至栈顶 |
faload | 无 | 将float型数组指定索引的值推送至栈顶 |
daload | 无 | 将double型数组指定索引的值推送至栈顶 |
aaload | 无 | 将引用型数组指定索引的值推送至栈顶 |
bastore | 无 | 将栈顶boolean或byte型数值存入指定数组的指定索引位置 |
castore | 无 | 将栈顶char型数值存入指定数组的指定索引位置 |
sastore | 无 | 将栈顶short型数值存入指定数组的指定索引位置 |
iastore | 无 | 将栈顶int型数值存入指定数组的指定索引位置 |
fastore | 无 | 将栈顶float型数值存入指定数组的指定索引位置 |
dastore | 无 | 将栈顶double型数值存入指定数组的指定索引位置 |
aastore | 无 | 将栈顶引用型数值存入指定数组的指定索引位置 |
3.方法调用和返回指令
调用之后的结果依旧是在操作栈的
操作码 | 操作数 | 备注 |
invokevirtual | 无 | 用于调用对象的实例方法,根据对象的实际类型进行分派(虚方法分派),这也是Java语言中最常见的方法分派方式。 |
invokeinterface | 无 | 用于调用接口方法,它会在运行时搜索一个实现了这个接口方法的对象,找出适合的方法进行调用。 |
invokespecial | 无 | 用于调用一些需要特殊处理的实例方法,包括实例初始化方法(§2.9)、私有方法和父类方法。 |
invokestatic | 无 | 调用类方法(static方法)。 |
ireturn | 无 | 从当前方法返回int |
lreturn | 无 | 从当前方法返回long |
areturn | 无 | 从当前方法返回对象引用 |
return | 无 | 从当前方法返回void |
4.其他操作
操作码 | 操作数 | 备注 |
monitorenter | 无 | 获得对象的锁,用于同步方法或同步块 |
monitorexit | 无 | 释放对象的锁,用于同步方法或同步块 |
athrow | 无 | 抛出异常信息 |
jsr | 无 | 跳转至指定16位offset位置,并将jsr下一条指令地址压入栈顶 |
jsr_w | 无 | 跳转至指定32位offset位置,并将jsr_w下一条指令地址压入栈顶 |
goto_w | 无 | 无条件跳转(宽索引) |
大多数的操作码已经在这两章中介绍了,小伙伴们可以简单的对自己的程序进行编译查看下操作码(javap -help
)。对于一些简单的程序就可以自己去查看。