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

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

MakeFunny发布于 2 月 2 日

Class类文件的结构

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

  • 无符号数:属于基本的数据类型,以u1、u2、u4、u8来分别表示一个字节、2个字节、4个字节和8个字节的无符号数。无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8编码构字符串值

  • 表:是由多个无符号数或者其他表作为数据项构成的符合数据类型,所有表的命名都以"_info""结尾

魔术(Magic Number)

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

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

Class文件版本号

  • 第五个和第六个字节代表编译的副版本号minor_version,第七个和第八个是编译的主版本号major_version

  • 版本号和Java编译器的对应关系

编译器版本主版本副版本
1.7510
1.8520

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

常量池

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

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

访问位置

  • 在常量池结束之后,紧接着的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."<init>":()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】Java虚拟机-Class类文件的结构

参考文章

  • Java虚拟机之Class类文件结构
  • 《深入理解Java虚拟机》(第三版)

点击查看原文

javajvmclassjps

阅读 5更新于 2 月 2 日

本作品系原创,采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议

avatar

MakeFunny

记录我的代码历程

10 声望

1 粉丝

0 条评论

得票时间

avatar

MakeFunny

记录我的代码历程

10 声望

1 粉丝

宣传栏

Class类文件的结构

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

  • 无符号数:属于基本的数据类型,以u1、u2、u4、u8来分别表示一个字节、2个字节、4个字节和8个字节的无符号数。无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8编码构字符串值

  • 表:是由多个无符号数或者其他表作为数据项构成的符合数据类型,所有表的命名都以"_info""结尾

魔术(Magic Number)

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

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

Class文件版本号

  • 第五个和第六个字节代表编译的副版本号minor_version,第七个和第八个是编译的主版本号major_version

  • 版本号和Java编译器的对应关系

编译器版本主版本副版本
1.7510
1.8520

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

常量池

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

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

访问位置

  • 在常量池结束之后,紧接着的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."<init>":()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】Java虚拟机-Class类文件的结构

参考文章

  • Java虚拟机之Class类文件结构
  • 《深入理解Java虚拟机》(第三版)

点击查看原文

以上是 【Java】Java虚拟机-Class类文件的结构 的全部内容, 来源链接: utcz.com/a/112300.html

回到顶部