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

文章目录

      • 0.java字节码整体结构
      • 1.魔数
      • 2.版本信息
      • 3.常量池
      • 4.常量池的总体结构

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

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
【jvm学习12】字节码结构(魔数,版本信息,常量池数量,常量池表)_第2张图片

0.java字节码整体结构

类型 名称 说明 长度
u4 magic 魔数,识别Class文件格式 4个字节
u2 minor_version 次版本号 2个字节
u2 major_version 主版本号 2个字节
u2 constant_pool_count 常量池个数 2个字节
cp_info constant_pool 常量池表 n个字节
u2 access_flags 访问标志 2个字节
u2 this_class 类索引 2个字节
u2 super_class 父类索引 2个字节
u2 interfaces_count 接口计数器 2个字节
u2 interfaces 接口索引集合 2个字节
u2 fields_count 字段个数 2个字节
field_info fields 字段集合 n个字节
u2 methods_count 方法计数器 2个字节
method_info methods 方法集合 n个字节
u2 attributes_count 附加属性计数器 2个字节
attribute_info attributes 附加属性集合 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中常量项的结构总表
【jvm学习12】字节码结构(魔数,版本信息,常量池数量,常量池表)_第3张图片
class字节码中有两种数据类型:

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

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

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

总体分析:
【jvm学习12】字节码结构(魔数,版本信息,常量池数量,常量池表)_第14张图片
根据IDEA带的javap -verbose命令反编译MyTest.class文件:
我们根据二进制数据分析出来的各个常量项和反编译的结果相同

Constant pool:
   #1 = Methodref          #4.#24         // java/lang/Object."":()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          // "":()V
  #25 = NameAndType        #5:#6          // a:I
  #26 = Utf8               com/hh/MyTest1
  #27 = Utf8               java/lang/Object

你可能感兴趣的:(JVM)