栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【JVM】JVM04(类加载与字节码-图解方法执行流程)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【JVM】JVM04(类加载与字节码-图解方法执行流程)

⭐️写在前面


这里是温文艾尔の学习之路如果对你有帮助,给博主一个免费的点赞以示鼓励把QAQ博客主页 温文艾尔の学习小屋⭐️更多文章‍请关注温文艾尔主页文章发布日期:2021.12.29java学习之路!欢迎各位点赞评论收藏⭐️新年快乐朋友们jvm学习之路!⭐️上一篇内容:【JVM】JVM03(图解垃圾回收机制)下

文章目录

1.字节码指令1.1入门1.2图解方法执行流程1.2.1常量池载入运行时常量池1.2.2方法字节码载入方法区1.2.3main线程开始运行,分配栈帧内存1.2.4执行引擎开始执行字节码


1.字节码指令 1.1入门

字节码指令可参考官方文档介绍
官方文档地址

1.2图解方法执行流程

原始java代码

public class Demo02 {
    public static void main(String[] args) {
        int a = 10;
        int b = Short.MAX_VALUE + 1;
        int c =a+b;
        System.out.println(c);
    }
}

通过javap工具反编译后的字节码文件

javap -v Demo02.class
Classfile /F:/2021年12月之后的Idea项目/jvmProject/out/production/jvmProj
ect/com/wql/jvm/ClassInfo/Demo02.class
  Last modified 2022年1月22日; size 624 bytes
  SHA-256 checksum dc35d1e7095f253b0d5f0c8f3209953eba9fa5fc94f05edc6bc90
2db4f70f6ac
  Compiled from "Demo02.java"
public class com.wql.jvm.ClassInfo.Demo02
  minor version: 0
  major version: 52
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #6                          // com/wql/jvm/ClassInfo/Demo0
2
  super_class: #7                         // java/lang/Object
  interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
   #1 = Methodref          #7.#25         // java/lang/Object."":(
)V
   #2 = Class              #26            // java/lang/Short
   #3 = Integer            32768
   #4 = Fieldref           #27.#28        // java/lang/System.out:Ljava/
io/PrintStream;
   #5 = Methodref          #29.#30        // java/io/PrintStream.println
:(I)V
   #6 = Class              #31            // com/wql/jvm/ClassInfo/Demo0
2
   #7 = Class              #32            // java/lang/Object
   #8 = Utf8               
   #9 = Utf8               ()V
  #10 = Utf8               Code
  #11 = Utf8               LineNumberTable
  #12 = Utf8               LocalVariableTable
  #13 = Utf8               this
  #14 = Utf8               Lcom/wql/jvm/ClassInfo/Demo02;
  #15 = Utf8               main
  #16 = Utf8               ([Ljava/lang/String;)V
  #17 = Utf8               args
  #18 = Utf8               [Ljava/lang/String;
  #19 = Utf8               a
  #20 = Utf8               I
  #21 = Utf8               b
  #22 = Utf8               c
  #23 = Utf8               SourceFile
  #24 = Utf8               Demo02.java
  #25 = NameAndType        #8:#9          // "":()V
  #26 = Utf8               java/lang/Short
  #27 = Class              #33            // java/lang/System
  #28 = NameAndType        #34:#35        // out:Ljava/io/PrintStream;
  #29 = Class              #36            // java/io/PrintStream
  #30 = NameAndType        #37:#38        // println:(I)V
  #31 = Utf8               com/wql/jvm/ClassInfo/Demo02
  #32 = Utf8               java/lang/Object
  #33 = Utf8               java/lang/System
  #34 = Utf8               out
  #35 = Utf8               Ljava/io/PrintStream;
  #36 = Utf8               java/io/PrintStream
  #37 = Utf8               println
  #38 = Utf8               (I)V
{
  public com.wql.jvm.ClassInfo.Demo02();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object
."":()V
         4: return
      LineNumberTable:
        line 9: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/wql/jvm/ClassInfo/Demo02;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: (0x0009) ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=4, args_size=1
         0: bipush        10
         2: istore_1
         3: ldc           #3                  // int 32768
         5: istore_2
         6: iload_1
         7: iload_2
         8: iadd
         9: istore_3
        10: getstatic     #4                  // Field java/lang/System.
out:Ljava/io/PrintStream;
        13: iload_3
        14: invokevirtual #5                  // Method java/io/PrintStr
eam.println:(I)V
        17: return
      LineNumberTable:
        line 11: 0
        line 12: 3
        line 13: 6
        line 14: 10
        line 15: 17
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      18     0  args   [Ljava/lang/String;
            3      15     1     a   I
            6      12     2     b   I
           10       8     3     c   I
}
SourceFile: "Demo02.java"

执行流程

1.2.1常量池载入运行时常量池

这里有一点误解,运行时常量池属于方法区,只是因为它相对比较特殊这里我们单独拎出来看,我们Class文件常量池中的数据,将来都要存储在运行时常量池

一些比较小的数字,比如int a=10;这些跟方法的字节码指令存在一起,而一旦数字的范围超过了整数最大值,他就会存储在常量池中,所以int b = Short.MAX_VALUE + 1;(32768)被存储在运行时常量池中

1.2.2方法字节码载入方法区

1.2.3main线程开始运行,分配栈帧内存

局部变量表是4,拥有4个槽位,栈的深度为2

绿色:局部变量表
蓝色:操作数栈

1.2.4执行引擎开始执行字节码

bipush 10

将一个byte压入操作数栈(其长度会补齐4个字节),类似的指令还有sipush将一个short压入操作数栈(其长度会补齐4个字节)ldc将一个int压入操作数栈ldc2_w将一个long压入操作数栈(分两次压入,因为long是8个字节)这里小的数字都是和字节码指令存在一起,超过short范围的数字存入了常量池

istore_1

将操作数栈顶数据弹出,存入局部变量表的slot1



ldc #3

从常量池加载#3数据到操作数栈

注意Short.MAX_VALUE是32767,所以32768 = Short.MAX_VALUE + 1实际是在编译期间计算好的

istore_2

将栈顶数据弹出放入局部变量表的2号槽位

此处可以发现,32768(Short.MAX_VALUE + 1)是在编译期间就已经计算好了的,

iload_1

将局部变量表中1槽位的值读取到操作数栈


iload_2

将局部变量表中2槽位的值读取到操作数栈


iadd

依次弹出操作数栈栈顶的两个数字,进行相加操作,计算完毕后将结果压入操作数栈中

结果32778被压入栈

istore3

将操作数栈顶的元素放入局部变量表的3号槽位


getstatic #4

到常量池中找到#4,发现是成员变量的引用,它的实际对象存放在堆内存中,通过常量池找到堆中的system对象,将对象的引用放入操作数栈



iload_3

将局部变量表中3号槽位的c压入到操作数栈



invokevirtual #5

到运行时常量池找到#5定位到方法区java/io/PrintStream.println:(I)v方法生成新的栈帧(分配locals、stack等)传递参数,执行新栈帧中的字节码

等待栈帧执行完毕,将栈帧弹出并清除main操作数栈内容
return完成main方法调用,弹出main栈帧程序结束

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/727294.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号