Java虚拟机-Class类文件的结构

Class类文件的结构

Class文件是一组以8个字节为基础单位的二进制流,各个数据严格按照顺序紧凑地排列在文件之中,中间没有添加任何分隔符。文件格式采用一宗类似于C语言结构体的伪结构来存储数据,这种伪结构只要两种数据类型:无符号数和表

  • 无符号数:属于基本的数据类型,以u1、u2、u4、u8来分别表示一个字节、2个字节、4个字节和8个字节的无符号数。无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8编码构字符串值
  • :是由多个无符号数或者其他表作为数据项构成的符合数据类型,所有表的命名都以"_info""结尾

魔术(Magic Number)

  • 每个Class文件开头的4个字节的无符号整数
  • 存在的作用是确定这个文件是一个能被虚拟机接受的有效合法的Class文件
  • 魔术值固定为0×CAFEBABE

Java虚拟机-Class类文件的结构_第1张图片

Class文件版本号

  • 第五个和第六个字节代表编译的副版本号minor_version,第七个和第八个是编译的主版本号major_version
  • 版本号和Java编译器的对应关系
编译器版本 主版本 副版本
1.7 51 0
1.8 52 0

Java虚拟机-Class类文件的结构_第2张图片

常量池

  • 主要存储:字面量和符号引用
  • 是Class文件结构中与其他项目关联最多的数据,也是占用Class文件空间最大的数据项目之一
  • 可以使用javap命令输出常量表

Java虚拟机-Class类文件的结构_第3张图片

访问位置

  • 在常量池结束之后,紧接着的2个字节代表访问标志,用于识别一些类或者接口层次的访问信息,包括:

    • 这个Class是类还是接口;
    • 是否定义了public类型;
    • 是否定义为abstract类型;
    • 如果是类,是否被声明为final等

类索引、父类索引与接口索引集合

类索引(this_class)和父类索引(super_class)都是一个u2类型的数据,而和接口索引(interfaces)是一组u2类型索引的结合,Class文件通过这三项数据来确定该类型的集成关系

字段表集合

字段表(field_info)用于描述接口或类中声明的变量。变量指类级变量和实例级变量,但不包括在方法内部声明的局部变量。描述字段的信息包括:

  1. 作用域(public private protected)
  2. 是实例变量还是类变量(static)
  3. 可变性(final)
  4. 并发可见性(volatile)
  5. 可否被序列化(transient)
  6. 字段数据类型(基本数据类型、对象和数组)

方法表集合

方法表集合和字段表集合结构类似,不同之处在于volatile和transient不能用于描述方法,所以方法表的访问标识中没有ACC_VOLATILE和`ACC_TRANSIENT

属性表集合

将如下代码编译之后使用javap指令查看属性集合内容

public class Test2021 {

    public void showMessage() {
        System.out.println("Hello World");
    }
}

使用java -v Test2021.class之后就可以看到属性表集合内存存储的数据

{
  public Test2021();
    descriptor: ()V
    // 类作用域
    flags: ACC_PUBLIC
    // 内部存储字节码指令
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."":()V
         4: return

      // Java源码行号与字节码指令的对应关系
      LineNumberTable:
        line 6: 0
      // 局部变量表
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   LTest2021;

  public void showMessage();
    descriptor: ()V
    // 方法作用域
    flags: ACC_PUBLIC

    // 内部存储字节码指令
    Code:
      stack=2, locals=1, args_size=1
         0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
         3: ldc           #3                  // String Hello World
         5: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
         8: return
      // Java源码行号与字节码指令的对应关系
      LineNumberTable:
        line 9: 0
        line 10: 8
      // 局部变量表
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       9     0  this   LTest2021;
}
// 源文件名称
SourceFile: "Test2021.java"

最新的《JAVA虚拟机规范-Java SE 8 Edition》中定义了23个属性:各属性代表的实际含义点击这里查看

Java虚拟机-Class类文件的结构_第4张图片

参考文章

点击查看原文

你可能感兴趣的:(javajvmclassjps)