JVM虚拟机:普通方法JVM指令流程图解

javap 指令能够将 .class 字节码指令反编译成人类稍微能够理解的代码

具体用法是 javap -v xxxx.class,-v 就是查看详细信息

下面是输出示例

//类基本信息
Classfile /E:/jvmdemo/代码/jvm/out/production/jvm/cn/itcast/jvm/t5/HelloWorld.class
  Last modified 2022-9-28; size 567 bytes // 最后修改时间
  MD5 checksum 8efebdac91aa496515fa1c161184e354
  Compiled from "HelloWorld.java" 
public class cn.itcast.jvm.t5.HelloWorld // 类的访问修饰符和包名类名
  minor version: 0
  major version: 52 // 对应 jdk1.8 版本
  flags: ACC_PUBLIC, ACC_SUPER
  this.class: #5 // 自己的类
  super.class: #6 // 父类
  interface: 0, fields: 0, method: 2, attributes: 1 // 接口

对应之前还需要查表的 .class 文件,这个就显得清晰明了

图解流程

请阅读下列代码

/**
 * 演示 字节码指令 和 操作数栈、常量池的关系
 */
public class Demo3_1 {
    public static void main(String[] args) {
        int a = 10; // valueOf 缓存
        int b = Short.MAX_VALUE + 1; // 超过 128 阈值,存入常量池
        int c = a + b;
        System.out.println(c);
    }
}

由于 valueOf 会缓存 -127~128 的整数,所以比较小的数会和字节码指令存放在一起,因为是缓存了所以字节码会直接从 Java 内存拿而不是去常量池取

下面是上述代码在运行时常量池的状况,参数类型是 I 表示要接收基本整数类型的参数
在这里插入图片描述

对于一些拿数据,调方法等字节码指令都会存入方法区,如下图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sbTLQEOe-1681264661926)(E:\mtdocument\mtdocument#图片存放\2022-11-21-21-58-51-image.png)]

然后就是 main 方法执行,开始分配栈帧内存,main 方法栈帧会多 2 块空间,一个是局部变量表,一个是操作数栈,这里分配了 4 个局部变量表和 2 个操作数栈,这是根据你定义了多少变量来动态变化的,这两个空间共同决定栈帧大小,这两个概念后面会说,图略

执行字节码指令

bipush 10 指令

可以看出,方法区指令码的第一个是 bipush 10,那么执行引擎就会读到这一行并开始执行

bipush 10 就是将一个 byte 的数字压入操作数栈中,因为我们声明了一个int类型的数字10,但是数值较小,用 byte 节约内存,由于一个操作数栈占 4 个字节,会自动补齐

类似的指令有 sipush 将一个 short 压入操作数栈,ldc 将一个 int 压入操作数栈,ldc2_w 将一个 long 压入操作数栈,由于操作数栈的一个单位是 4 字节,所以分两次压入,因为 long 是 8 个字节

这个例子中操作数栈有 2 个,每个有 4 个字节,局部变量表有 4 个 (stack=2,locals=4)

istore 1 指令


在这里插入图片描述

istore 就是把操作数栈栈顶数据弹出,存到局部变量表中,后面的 1 表示要存到哪个槽位,这里明显要放到 1 号槽位中

ldc #3

从常量池加载 #3 数据到操作数栈
在这里插入图片描述

istore 2

这我就不解释了,看图

在这里插入图片描述

iload 1
iload 2

这两个指令就是把 1 和 2 槽位的值读到操作数栈,注意是读取不是移动,看图

在这里插入图片描述

iadd

会让操作数栈弹出 2 个值,让 2 个值进行相加操作,然后把结果存回操作数栈

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AvbPtWBy-1681264661948)(E:\mtdocument\mtdocument#图片存放\2022-11-21-22-31-12-image.png)]

istore 3

不想解释了,自己猜吧

getstatic #4

接下来要执行打印操作了,从常量池中找到成员变量的引用,通过这个引用找到堆中 System.out 对象,getstatic 不会把 out 对象放入操作数栈,而是获取 out 引用,并放入操作数栈

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-unqvrg7T-1681264661950)(E:\mtdocument%23图片存放\2022-11-21-22-36-45-image.png)]

iload 3

把操作数栈 3 号槽位的值读入操作数栈
在这里插入图片描述

invokevirtual #5

找到常量池的 #5,是个方法引用,根据引用定位方法区java/io/PrintStream.println:(I)V ,然后会生成新的栈帧,并分配 locals、stack,传递参数,执行打印操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fbIyQ9gy-1681264661955)(E:\mtdocument\mtdocument#图片存放\2022-11-21-22-44-01-image.png)]

return

弹出 main 栈帧

下面摆一个 JVM 指令码的例子,提前熟悉一下

  1. 操作数栈
    变量到操作数栈:iload,iload_,lload,lload_,fload,fload_,dload,dload_,aload,aload_
    操作数栈到变量:istore,istore_,lstore,lstore_,fstore,fstore_,dstore,dstor_,astore,astore_
    常数到操作数栈:bipush,sipush,ldc,ldc_w,ldc2_w,aconst_null,iconst_ml,iconst_,lconst_,fconst_,dconst_
    把数据装载到操作数栈:baload,caload,saload,iaload,laload,faload,daload,aaload
    从操作数栈存存储到数组:bastore,castore,sastore,iastore,lastore,fastore,dastore,aastore
    操作数栈管理:pop,pop2,dup,dup2,dup_xl,dup2_xl,dup_x2,dup2_x2,swap
  2. 运算与转换
    加:iadd,ladd,fadd,dadd
    减:is ,ls ,fs ,ds
    乘:imul,lmul,fmul,dmul
    除:idiv,ldiv,fdiv,ddiv
    余数:irem,lrem,frem,drem
    取负:ineg,lneg,fneg,dneg
    移位:ishl,lshr,iushr,lshl,lshr,lushr
    按位或:ior,lor
    按位与:iand,land
    按位异或:ixor,lxor

详细请参考以下网址,访问网址可以使用 ctrl+f 进行查找

负:ineg,lneg,fneg,dneg
移位:ishl,lshr,iushr,lshl,lshr,lushr
按位或:ior,lor
按位与:iand,land
按位异或:ixor,lxor

详细请参考以下网址,访问网址可以使用 ctrl+f 进行查找

JVM指令集及各指令的详细使用说明 - 腾讯云

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值