JVM指令手册

本文详细介绍了JVM的各种指令,包括加载存储、运算、类型转化、对象创建与访问、操作数栈管理和控制转移等,旨在帮助读者掌握Java字节码的执行原理。
摘要由CSDN通过智能技术生成

反汇编字节码:

javap -c 字节码文件名 > 文本文件名

局部变量0——this

所有机器指令的执行都是在栈帧中入栈出栈完成的,局部变量表会随时负责进行变量创建,操作数入栈等工作

在这里插入图片描述

加载存储:

·将一个局部变量加载到操作栈: iload、 iload_<n>、 lload、 lload_<n>、 fload、 fload_<n>、 dload、dload_<n>、 aload、 aload_<n>
·将一个数值从操作数栈存储到局部变量表: istore、 istore_<n>、 lstore、 lstore_<n>、 fstore、fstore_<n>、 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

运算:

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

类型转换:

·int类型到long、 float或者double类型
·long类型到float、 double类型
·float类型到double类型
与之相对的, 处理窄化类型转换(Narrowing Numeric Conversion) 时, 就必须显式地使用转换指
令来完成, 这些转换指令包括i2b、 i2c、 i2s、 l2i、 f2i、 f2l、 d2i、 d2l和d2f。

对象创建与访问

·创建类实例的指令: 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

操作数栈管理:

·将操作数栈的栈顶一个或两个元素出栈: pop、 pop2
·复制栈顶一个或两个数值并将复制值或双份的复制值重新压入栈顶: dup、 dup2、 dup_x1、
dup2_x1、 dup_x2、 dup2_x2
·将栈最顶端的两个数值互换: swap

控制转移

·条件分支: 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

方法调用与返回

·invokevirtual指令: 用于调用对象的实例方法, 根据对象的实际类型进行分派(虚方法分派) ,这也是Java语言中最常见的方法分派方式。
·invokeinterface指令: 用于调用接口方法, 它会在运行时搜索一个实现了这个接口方法的对象, 找出适合的方法进行调用。
·invokespecial指令: 用于调用一些需要特殊处理的实例方法, 包括实例初始化方法、 私有方法和父类方法。
·invokestatic指令: 用于调用类静态方法(static方法) 。
·invokedynamic指令: 用于在运行时动态解析出调用点限定符所引用的方法。 并执行该方法。

前面四条调用指令的分派逻辑都固化在Java虚拟机内部, 用户无法改变, 而invokedynamic指令的分派逻辑是由用户所设定的引导方法决定的。

代码同步演示

void onlyMe(Foo f) {
   synchronized(f) {
      doSomething();
   }
}

编译后, 这段代码生成的字节码序列如下:

Method void onlyMe(Foo)
0 aload_1 // 将对象f入栈
1 dup // 复制栈顶元素(即f的引用)
2 astore_2 // 将栈顶元素存储到局部变量表变量槽 2中
3 monitorenter // 以栈定元素(即f) 作为锁, 开始同步
4 aload_0 // 将局部变量槽 0(即this指针) 的元素入栈
5 invokevirtual #5 // 调用doSomething()方法
8 aload_2 // 将局部变量Slow 2的元素(即f) 入栈
9 monitorexit // 退出同步
10 goto 18 // 方法正常结束, 跳转到18返回
13 astore_3 // 从这步开始是异常路径, 见下面异常表的Taget 13
14 aload_2 // 将局部变量Slow 2的元素(即f) 入栈
15 monitorexit // 退出同步
16 aload_3 // 将局部变量Slow 3的元素(即异常对象) 入栈
17 athrow // 把异常对象重新抛出给onlyMe()方法的调用者
18 return // 方法正常返回
Exception table:
FromTo Target Type
4 10 13 any
13 16 13 any
 

一、未归类系列A

此系列暂未归类。
指令码 助记符 说明
0x00 nop 什么都不做
0x01 aconst_null 将null推送至栈顶

二、const系列:压入操作数栈

该系列命令主要负责把简单的数值类型送到栈顶。该系列命令不带参数。注意只把简单的数值类型送到操作数栈顶时,才使用如下的命令。
比如对应int型才该方式只能把-1,0,1,2,3,4,5(分别采用iconst_m1,iconst_0, iconst_1, iconst_2, iconst_3,iconst_4, iconst_5)送到栈顶。对于int型,其他的数值请使用push系列命令(比如bipush)。

指令码    
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pub.ryan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值