字节码指令

1、加载与存储指令

  • xload、xload_<n>(x为i、l、f、d、a,n为索引0、1、2、3):将局部变量加载到操作数栈

    • iload_0:将局部变量0入栈;和 iload 0 一样,但 iload 0占3个字节,iload_0只占1个字节;若n>3,则使用 iload 4

    • iload 4:将局部变量4入栈

  • iconst_m1、iconst<i>、lconst<l>、fconst<f>、dconst<d>、aconst_null、bipush、sipush、ldc、ldc_w、ldc2_w:将常量加载到操作数栈

    • iconst_m1:将int型常量-1入栈

    • iconst_<i>(i为数值-1到5):将int型常量-1到5入栈

    • lconst_<l>(l为数值0到1):将long型常量0到1入栈

    • fconst_<f>(f为数值0到2):将float型常量0到2入栈

    • dconst_<d>(d为数值0到1):将double型常量0到1入栈

    • aconst_null:将null入栈

    • bipush <i>:将8位int型常量(-128 - 127)入栈

    • sipush <i>:将16位int型常量(-32768 - 32767)入栈

    • ldc <n>:将8位参数(int、float、String)常量池中的索引位置的数据入栈

    • ldc_w <n>:将16位参数(int、float、String)常量池中的索引位置的数据入栈

    • ldc2_w <n>:将16位参数(long、double)常量池中的索引位置的数据入栈

  • xstore、xstore_<n>(x为i、l、f、d、a,n为索引0、1、2、3)、xastore(x为i、l、f、d、a、b、c、s):将数值从操作数栈存储到局部变量表

    • istore_0:将操作数栈顶的int型数据存储到局部变量表中索引为0的位置

    • istore 4:将操作数栈顶的int型数据存储到局部变量表中索引为4的位置

  • wide:局部变量表访问索引

2、算数指令

  • 加法指令:iadd、ladd、fadd、dadd

  • 减法指令:isub、lsub、fsub、dsub

  • 乘法指令:imul、lmul、fmul、dmul

  • 除法指令:idiv、ldiv、fdiv、ddiv

  • 求余指令(余数:remainder):irem、lrem、frem、drem

  • 取反指令(取反:negation):ineg、lneg、fneg、dneg

  • 自增指令:iinc

    • iinc 1 by 2:将局部变量表中索引为1的int型整数加上2

  • 位运算指令

    • 位移指令:ishl、ishr、iushr、lshl、lshr、lush

    • 按位或指令:ior、lor

    • 按位与指令:iand、land

    • 按位异或指令:ixor、lxor

  • 比较指令:dcmpg、dcmpl、fcmpg、fcmpl、lcmp

    • 比较栈顶两个元素的大小,栈顶下一个元素比栈顶元素比较,大于返回1,相等返回0、小于返回-1

    • dcmpg和dcmpl:针对double类型数据,由于0.0/0.0的结果为NaN,dcmpg会压入1,dcmpl会压入-1

    • fcmpg和fcmpl:针对float类型数据,同上

    • lcmp:由于long型没有NaN值,不需要区分

3、类型转换指令

  • 宽化类型转换

    • i2l、i2f、i2d:将int型(byte、short、char都看作int)转为long、float、double

    • l2f、l2d:将long型转为float、double

    • f2d:将float型转为double

  • 窄化类型转换

    • i2b、i2s、i2c:将int型转为byte、short、char

    • l2i:将long型转为int

    • f2i、f2l:将float型转为int、long

    • d2i、d2l、d2f:将double型转为int、long、float

    • 将long型转为byte:l2i,i2b

4、对象创建与访问指令

  • 创建指令

    • new:创建类实例,并将堆中的引用入栈

    • newarray:创建基本类型数组,并将堆中的引用入栈

    • anewarray:创建引用类型数组,并将堆中的引用入栈

    • multianewarray:创建多维数组,并将堆中的引用入栈

  • 字段访问指令

    • getstatic:将类变量入栈

    • putstatic:将类变量出栈

    • getfield:将实例变量入栈

    • putfield:将实例变量出栈

  • 数组操作指令

    • baload(byte和boolean)、caload、saload、iaload、laload、faload、daload、aaload:将数组元素入栈

      • xaload执行时,要求操作数栈顶元素为数组索引i,栈顶顺位第2个元素为数组引用a,该指令弹出栈顶两个元素,并将a[i]重新入栈

    • bastore(byte和boolean)、castore、sastore、iastore、lastore、fastore、dastore、aastore:将栈的值存储到数组中

      • xastore执行前,操作数栈顶需要三个元素:值、索引、数组引用,xastore会弹出这3个值,并将值赋给数组中指定索引的位置

    • arraylength:弹出栈顶数组元素,获取数组长度,将长度入栈

  • 类型检查指令

    • instanceof:判断对象是否为一个类的实例,将结果入栈

    • checkcast:检查类型强制转换是否可以进行;若可以,不会改变栈,否则抛出ClassCastException

5、方法调用与返回指令

  • 方法调用指令(调用完会将栈顶两个元素出栈)

    • invokevirtual:调用虚方法,编译期间不能确定的方法;除去final修饰的方法(final修饰的方法是非虚方法),调用的都是虚方法

    • invokeinterface:调用接口方法,编译期间不能确定的方法;调用的都是虚方法

    • invokespecial:调用构造器<init>、私有、父类方法,编译期间可以确定的方法;调用的都是非虚方法

    • invokestatic:调用静态方法,编译期间可以确定的方法;调用的都是非虚方法

    • invokedynamic:动态解析需要调用的方法,再执行,编译期间不能确定的方法;主要体现在lambda表达式

  • 方法返回指令

    • ireturn(方法返回值为boolean、byte、char、short、int)、lreturn、freturn、dreturn、areturn:将当前操作数栈顶元素弹出,将此元素压入调用者函数的操作数栈中

    • return:方法返回值为void、实例初始化方法、类和接口初始化方法

6、操作数栈管理指令

  • pop、pop2:出栈

    • pop:弹出栈顶一个槽位大小(4个字节)的数据,例如一个int型数据、一个float型数据

    • pop2:弹出栈顶两个槽位大小(8个字节)的数据,例如两个int型数据、一个long型数据

  • dup、dup2、dup_x1、dup2_x1、dup_x2、dup2_x2:复制栈顶一个或两个数并将复制值或双份复制值重新入栈

    • dup:复制一个字节大小的数据

    • dup2:复制两个字节大小的数据

    • dup_x1:复制一个字节大小的数据,并将复制的数据插入到栈顶2个(1+1,dup和x后的系数相加)槽位下

    • dup2_x1:复制两个字节大小的数据,并将复制的数据插入到栈顶3个(2+1,dup和x后的系数相加)槽位下

  • slot:将栈顶两个槽位的数值交换

  • nop:什么都不做,通常用于调试和占位

7、控制转移指令

  • 条件跳转指令

    • ifeq、ifne、iflt、ifle、ifgt、ifge、ifnull、ifnonnull:弹出栈顶元素,满足某一条件时,跳转到给定位置(boolean、byte、char、short都按照int型处理)

      • ifeq:栈顶int型数值等于0时跳转

      • ifne:栈顶int型数值不等于0时跳转

      • iflt:栈顶int型数值小于0时跳转

      • ifle:栈顶int型数值小于等于0时跳转

      • ifgt:栈顶int型数值大于0时跳转

      • ifge:栈顶int型数值大于等于0时跳转

      • ifnull:为null时跳转

      • ifnonnull:不为null时跳转

  • 比较条件跳转指令

    • if_icmpeq、if_icmpne、if_icmplt、if_icmple、if_icmpgt、if_icmpge、if_acmpeq、if_acmpne:比较并跳转

      • if_icmpeq:比较栈顶两个int型数值大小,栈顶下一个元素等于栈顶元素时跳转

      • if_icmpne:比较栈顶两个int型数值大小,栈顶下一个元素不等于栈顶元素时跳转

      • if_icmplt:比较栈顶两个int型数值大小,栈顶下一个元素小于栈顶元素时跳转

      • if_icmple:比较栈顶两个int型数值大小,栈顶下一个元素小于等于栈顶元素时跳转

      • if_icmpgt:比较栈顶两个int型数值大小,栈顶下一个元素大于栈顶元素时跳转

      • if_icmpge:比较栈顶两个int型数值大小,栈顶下一个元素大于等于栈顶元素时跳转

      • if_acmpeq:比较栈顶两个引用类型数值,相等时跳转

      • if_acmpne:比较栈顶两个引用类型数值,不相等时跳转

  • 多条件分支跳转

    • tableswitch:用于switch条件中case值连续时跳转

    • lookupswitch:用于switch条件中case值不连续时跳转,出于效率考虑,会将case值进行大小排序

      • 若switch后的值为String(JDK7新特性),会计算每个case对应的String的哈希值进行大小排序;哈希值相等了在进行equals()比较

  • 无条件跳转

    • goto:接收两个字节的操作数(偏移量),直接跳转

    • goto_w:接收四个字节的操作数(偏移量),直接跳转

8、异常处理指令

  • athrow:显示抛出异常(throw语句)

    • 编译时异常和手动thow的异常都会用athrow声明,运行时异常不会用athrow声明

  • 异常表:使用try-catch、try-catch、try-catch-finally时会生成异常表

9、同步控制指令

  • 方法级同步:方法声明为synchronized时,没有在字节码指令中体现,而是在方法表结构中标注为synchronized

  • 代码块同步:同步的代码在monitorenter和monitorexit之间

    • monitorenter:将对象监视器的计数器改为1(加锁)

    • monitorexit:将对象监视器的计数器改为0(解锁)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值