【jvm学习12】字节码结构(魔数,版本信息,常量池数量,常量池表)


在这里插入图片描述

public class MyTest1 {
    private int a=1;
    public MyTest1() {
    }
    public int getA() {
        return a;
    }
    public void setA(int a) {
        this.a = a;
    }
}

使用WinHex打开这个类的字节码文件:MyTest1.class
在这里插入图片描述

0.java字节码整体结构

类型名称说明长度
u4magic魔数,识别Class文件格式4个字节
u2minor_version次版本号2个字节
u2major_version主版本号2个字节
u2constant_pool_count常量池个数2个字节
cp_infoconstant_pool常量池表n个字节
u2access_flags访问标志2个字节
u2this_class类索引2个字节
u2super_class父类索引2个字节
u2interfaces_count接口计数器2个字节
u2interfaces接口索引集合2个字节
u2fields_count字段个数2个字节
field_infofields字段集合n个字节
u2methods_count方法计数器2个字节
method_infomethods方法集合n个字节
u2attributes_count附加属性计数器2个字节
attribute_infoattributes附加属性集合n个字节

1.魔数

所有的.class字节码文件的前4个字节都是魔数,魔数值为固定值:0xCAFEBABE
在这里插入图片描述

2.版本信息

魔数之后的4个字节为,前两个字节表示minor version(次版本),后两个字节表示major version(主版本号)
这里的版本号为00 00 00 34,换算成十进制,表示次版本号为0,主版本号为52,所以该文件的版本号为:1.8.0
在这里插入图片描述

3.常量池

  • 紧接着版本号之后的就是常量池入口,一个java类中定义的很多信息都是由常量池来维护和描述的,可以将常量池看作是class文件的资源仓库。比如说:java类中定义的方法与变量信息,都是存储在常量池中。
  • 常量池中主要存储两类常量:字面量与符号引用。字面量如文本字符串,java中声明为final的常量值等,而符号引用如类和接口的全局限定名,字段的名称和描述符,方法的名称和描述符。

4.常量池的总体结构

  1. Java类所对应的常量池主要由常量池数量和常量池数组这两部分构成,常量池数量紧跟在主版本号后面,占据两个字节;
    常量池数组中的元素的个数=常量池数-1(其中0暂时不使用),目的是满足某些常量池索引值的数据在特定情况下需要表达[不引用任何一个常量池]的含义;根本原因在于索引为0也是一个常量(保留常量),只不过它不位于常量表中,这个常量就对应于null值。在这里插入图片描述
  2. 常量池数组紧跟在常量池数量之后。常量池数组与一般的数组不同的是,常量池数组中不同元素的类型,结构都是不同的,长度当然也不同;但是每一种元素的第一个数据都是一个u1类型,该字节是标志位,占据1个字节。jvm在解析常量池时,会根据这个u1类型来获取元素的具体类型。

下面根据使用WinHex软件显示的MyTest1.class在计算机磁盘中保存的16进制数据,反推出MyTest1.class的内容:
            常量池中14中常量项的结构总表
在这里插入图片描述
class字节码中有两种数据类型:

  1. 字节数据直接量:这是基本的数据类型,细分为u1,u2,u4,u8四种,分别代表连续的1个字节,2个字节,4个字节,8个字节组成的整体数据。
  2. 表(数组):表是由多个基本数据或其他表,按照既定顺序组成的大的数据集合,表是有结构的,他的结构体现在:组成表的成分所在的位置和顺序都是已经严格定义好的。(比如常量池项结构表)
               常量池中14中常量项的结构总表
    在这里插入图片描述

常量池数组紧跟在常量池数量之后。常量池数组与一般的数组不同的是,常量池数组中不同元素的类型,结构都是不同的,长度当然也不同;但是每一种元素的第一个数据都是一个u1类型,该字节是标志位,占据1个字节。
在这里插入图片描述
第1个常量
1.先找到常量池数组中元素的标志位u1对应的值:u1=10
在这里插入图片描述
2.查表u1=10:
由表可得,u1后面有2个索引项,总共占据4个字节,其中前两个字节代表类描述符的索引项,后两个字节代表类型描述符的索引项。
在这里插入图片描述
第2个常量
接着往下走,先找u1标志位对应的值:u1=9
在这里插入图片描述
查表u1=9:
u1=9,有两个索引项,占据4个字节,前两个字节代表声明字段的类或者接口描述符的索引项,后两个字节代表字段描述符的索引项。
在这里插入图片描述
在这里插入图片描述
第3个常量
先找u1标志位对应的值:u1=7
在这里插入图片描述
查表的u1=7:
u1=7后面有一个索引项,占据2个字节,代表全限定类名常量项的索引
在这里插入图片描述
在这里插入图片描述
第4个常量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第5个常量
首先确定u1的值:
在这里插入图片描述
根据u1=1进行查表:
由表可得,有两项内容:
一个是length,占据两个字节,代表字符串占用的字节数
一个是bytes,代表长度为length的字符串
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第6个变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第7个变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第8个变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第9个变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第10个变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

第11个变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第12个变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第13个变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第14个变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第15个变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第16个变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第17个变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第18个变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第19个变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第20个变量
在这里插入图片描述
第21个变量
在这里插入图片描述
第22个变量
在这里插入图片描述
第23个变量
在这里插入图片描述
第24个变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第25个变量
在这里插入图片描述
在这里插入图片描述
第26个变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第27个变量
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

总体分析:
在这里插入图片描述
根据IDEA带的javap -verbose命令反编译MyTest.class文件:
我们根据二进制数据分析出来的各个常量项和反编译的结果相同

Constant pool:
   #1 = Methodref          #4.#24         // java/lang/Object."<init>":()V
   #2 = Fieldref           #3.#25         // com/hh/MyTest1.a:I
   #3 = Class              #26            // com/hh/MyTest1
   #4 = Class              #27            // java/lang/Object
   #5 = Utf8               a
   #6 = Utf8               I
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lcom/hh/MyTest1;
  #14 = Utf8               getA
  #15 = Utf8               ()I
  #16 = Utf8               setA
  #17 = Utf8               (I)V
  #18 = Utf8               main
  #19 = Utf8               ([Ljava/lang/String;)V
  #20 = Utf8               args
  #21 = Utf8               [Ljava/lang/String;
  #22 = Utf8               SourceFile
  #23 = Utf8               MyTest1.java
  #24 = NameAndType        #7:#8          // "<init>":()V
  #25 = NameAndType        #5:#6          // a:I
  #26 = Utf8               com/hh/MyTest1
  #27 = Utf8               java/lang/Object
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我一直在流浪

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

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

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

打赏作者

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

抵扣说明:

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

余额充值