字节码指令分类

1、加载和存储指令

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

  • 将一个局部变量加载到操作栈:iload、iload_、lload、lload_、fload、fload_、dload、dload_、aload、aload_

  • 将一个数值从操作数栈存储到局部变量表:istore、istore_、lstore、lstore_、fstore、fstore_、dstore、dstore_、astore、astore_

  • 将一个常量加载到操作数栈:bipush、sipush、ldc、ldc_w、ldc2_w、aconst_null、iconst_m1、iconst_、lconst_、fconst_、dconst_

  • 扩充局部变量表的访问索引的指令:wide

存储数据的操作数栈和局部变量表主要由加载和存储指令进行操作,除此之外,还有少量指令,如访问对象的字段或数组元素的指令也会向操作数栈传输数据。

 

 

2、算术指令

用于对两个操作数栈上的值进行某种特定运算,并把结果重新存入到操作栈顶

  • 加法指令: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

 

分为两种:对整型数据进行运算的指令与对浮点型数据进行运算的指令。

不存在直接支持 byte、short、char 和 boolean 类型的算术指令,这几种数据的运算使用操作 int 类型的指令代替。

数据运算可能会导致溢出。

只有除法指令(idiv 和 ldiv)以及求余指令(irem 和 lrem)中除数为零时会导致虚拟机抛出 ArithmeticException 异常,其余任何整型数运算都不应该抛出运行时异常。

 

 

3、类型转换指令

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

JVM 直接支持以下数值类型的宽化类型转换(WideningNumeric Conversion):

  • int -> long、float、double

  • long -> float、double

  • float -> double

与之相对的,处理窄化类型转换(Narrowing Numeric Conversion)就必须显式地使用转换指令来完成

  • i2b

  • i2c

  • i2s

  • l2i

  • f2i

  • f2l

  • d2i

  • d2l

  • d2f

窄化类型转换可能会导致转换结果产生不同的正负号、不同的数量级、数值的精度丢失的情况。

 

 

4、对象创建与访问指令

虽然类实例和数组都是对象,但 JVM 对类实例和数组的创建与操作使用了不同的字节码指令

 

创建

  • 创建类实例的指令:new

  • 创建数组的指令:newarray、anewarray、multianewarray

 

类实例的字段、数组元素的访问

  • 访问类字段(static 字段)和实例字段(非 static 字段)的指令:getfield、putfield、getstatic、putstatic

  • 把一个数组元素加载到操作数栈的指令:baload、caload、saload、iaload、laload、faload、daload、aaload

  • 将一个操作数栈的值储存到数组元素中的指令:bastore、castore、sastore、iastore、fastore、dastore、aastore

  • 取数组长度的指令:arraylength

  • 检查类实例类型的指令:instanceof、checkcast

 

 

5、操作数栈管理指令

  • 将操作数栈的栈顶一个或两个元素出栈:pop、pop2

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

  • 将栈最顶端的两个数值互换:swap

 

 

6、控制转移指令

让 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

 

 

7、方法调用和返回指令

  • invokevirtual:用于调用对象的实例方法,根据对象的实际类型进行分派

  • invokeinterface:用于调用接口方法,它会在运行时搜索一个实现了这个接口方法的对象,找出适合的方法进行调用

  • invokespecial:用于调用一些需要特殊处理的实例方法,包括实例初始化方法、私有方法和父类方法

  • invokestatic:用于调用类静态方法

  • invokedynamic:用于在运行时动态解析并执行调用点限定符所引用的方法

  • 方法返回指令是根据返回值的类型区分的,包括 ireturn(返回 boolean、byte、char、short、int)、lreturn、freturn、dreturn、areturn、return(返回 void;类、接口、实例初始化方法)

 

 

 

8、异常处理指令

  • throw 语句抛出异常由 athrow 指令来实现

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

  • catch 语句早期版本使用 jsr 和 ret 指令来实现,现在采用异常表来完成

 

 

9、同步指令

  • 方法级的同步:ACC_SYNCHRONIZED

  • 方法内同步:monitorenter、monitorexit

 

 


【Java学习资源】整理推荐

  • MAT 分析堆内存快照
  • jclasslib 查看类信息
  • 增大 MAT 堆内存
  • JVM 常用配置参数(Java 8)
  • 40 道JVM面试题解答
  • JVM 问题排查常用指令
  • jvisualvm 远程连接服务器 JVM
  • 字节码指令分类
  • -verbose:gc 和 -XX:+PrintGC 的区别
  • JVM字节码指令表
  • 图解 Class 文件结构
  • Class 文件的结构
  • JVM 故障处理工具列表
  • HotSpot 内存分配的主要规则
  • 开启 GC 日志
  • 垃圾收集器及特点
  • JVM垃圾回收算法
  • 什么样的 Java 对象会被当垃圾回收?
  • 内存溢出复现
  • HotSpot VM 中对象的内存分析
  • JVM 控制的内存区域
  • JVM家族
  • Java 的发展史
  • 常见 JVM dump 指令

 

 


【Java面试题与答案】整理推荐

  • 基础与语法
  • 集合
  • 网络编程
  • 并发编程
  • Web
  • 安全
  • 设计模式
  • 框架
  • 算法与数据结构
  • 异常
  • 文件解析与生成
  • Linux
  • MySQL
  • Oracle
  • Redis
  • Dubbo

 

你可能感兴趣的:(字节码指令分类)