Java高级——字节码指令

字节码指令

JVM采用操作数栈架构,指令由操作码Opcode+操作数Operand构成

  • 大多指令不包含操作数,只有一个操作码,指令参数放在操作数栈
  • 操作码长度为一个字节,故总数不能超过256
  • 操作数未长度对齐,需在运行时重构回去
  • 操作码隐含数据类型,如iload从局部变量表中加载int数据到操作数栈中,a代表reference
  • byte和short符号扩展为int,boolean和char零位扩展为int

加载和存储指令

用于将数据在栈帧中的局部变量表和操作数栈之间的来回传输

  • 将一个局部变量加载到操作数栈:iload、iload_<n>、lload、lload_<n>、fload、fload_<n>、dload、dload_<n>、aload、aload_<n>
  • 将一个数值从操作数栈存储到局部变量表:istore、istore_<n>、lstore、lstore_<n>、fstore、fstore_、dstore、dstore_<n>、astore、astore_<n>
  • 将一个常量加载到操作数栈:bipush、sipush、ldc、ldc_w、ldc2_w、aconst_null、iconst_m1、iconst_<i>、lconst_<l>、fconst_<f>、dconst_<d>
  • 扩充局部变量表的访问索引的指令:wide

其中n代表数字,将操作数隐含到指令中

运算指令

用于对两个操作数栈上的值进行某种特定运算,并把结果重新存入到操作栈顶,可分为对整数和对浮点数进行运算的指令

  • 加:iadd、ladd、fadd、dadd
  • 减:isub、lsub、fsub、dsub
  • 乘:imul、lmul、fmul、dmul
  • 除:idiv、ldiv、fdiv、ddiv
  • 求余:irem、lrem、frem、drem
  • 取反:ineg、lneg、fneg、dneg
  • 位移:ishl、ishr、iushr、lshl、lshr、lushr
  • 或:ior、lor
  • 与:iand、land
  • 异或:ixor、lxor
  • 自增:iinc
  • 比较:dcmpg、dcmpl、fcmpg、fcmpl、lcmp

整型数据运算可能会导致溢出

除和求余中当除数为0时抛出ArithmeticException异常

类型转换指令

将两种不同的数值类型相互转换,一般用于显示转换

JVM直接支持宽化类型转换,无需显示的转换

  • int 转为 long、float、double
  • long 转为 float、double
  • float 转为 double

而窄化类型转换,必须显式使用转换指令

  • i2b、i2c、i2s、l2i、f2i、f2l、d2i、d2l、d2f

int或long窄化转换为其他整型时直接高位截断,可能导致符号位改变

浮点值窄化转换为其他整型时

  • 若为NaN,结果为0
  • 若是无穷大,则向零舍入取整,若取整后不在表示范围,则为最大或最小正数

doulbe转为float时

  • 向最接近数舍入
  • 若转换结果的绝对值太小,则返回float的正负0
  • 若转换结果的绝对值太大,则返回float类型的正负无穷大
  • NaN依旧为NaN

对象创建和访问指令

用于创建和访问对象和数组实例

  • 创建类:new
  • 创建数组:newarray、anewarray、multianewarray
  • 访问字段:getfield、putfield、getstatic、putstatic
  • 把数组元素加载到操作数栈:baload、caload、saload、iaload、laload、faload、daload、aaload
  • 将操作数栈的值存到数组:bastore、castore、sastore、iastore、fastore、dastore、aastore
  • 取数组长度:arraylength
  • 检查类型:instanceof、checkcast

操作数栈管理指令

用于直接操作操作数栈

  • 出栈:pop、pop2
  • 复制栈顶元素并入栈:dup、dup2、dup_x1、dup2_x1、dup_x2、dup2_x2
  • 将栈顶两元素互换:swap

控制转移指令

让JVM有条件或无条件地从指定位置指令的下一条指令继续执行程序

  • 条件分支:ifeq、iflt、ifle、ifne、ifgt、ifge、ifnull、ifnonnull、if_icmpeq、if_icmpne、if_icmplt、if_icmpgt、if_icmple、if_icmpge、if_acmpeq、if_acmpne
  • 复合条件分支:tableswitch、lookupswitch
  • 无条件分支:goto、goto_w、jsr、jsr_w、ret

long、float、double的条件分支操作,会先执行比较运算指令得到int值,再执行int类型的条件分支指令来完成分支跳转

方法调用和返回指令

方法调用

  • invokevirtual:调用对象实例方法,根据对象的实际类型进行分派(虚方法分派)
  • invokeinterface:调用接口方法,会在运行时搜索实现这个接口方法的对象,找出适合的方法进行调用
  • invokespecial:调用一些需要特殊处理的实例方法,包括构造方法、私有方法和父类方法
  • invokestatic:调用static方法
  • invokedynamic:在运行时动态解析出调用点限定符所引用的方法并执行,分派逻辑由用户所设定的引导方法决定

方法返回

  • ireturn、lreturn、freturn、dreturn、areturn,return(void)

异常处理指令

显式抛出异常的操作(throw语句)都由athrow指令来实现

运行时异常会在其他指令检测到异常时自动抛出

处理异常(catch语句)不由字节码指令实现,而是采用异常表

同步指令

JVM通过管程(Monitor)可以支持方法级的同步和方法内部一段指令序列的同步

方法级的同步无须通过字节码指令来控制,当方法调用时检查ACC_SYNCHRONIZED,如果设置了,线程就要先持有管程才能执行方法,方法完成时释放管程

同步一段指令序列由synchronized语句块表示,monitorenter和monitorexit实现

大全

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值