从 HelloWorld 看 Java 字节码文件结构(2)

Class 文件的第 1 - 4 个字节代表了该文件的魔数(Magic Number)。它唯一的作用是确定这个文件是否为一个能被虚拟机接受的 Class 文件,其值固定是:0xCAFEBABE(咖啡宝贝)。如果一个 Class 文件的魔数不是 0xCAFEBABE,那么虚拟机将拒绝运行这个文件。

Class 文件的第 5 - 6 个字节代表了 Class 文件的次版本号(Minor Version),即编译该 Class 文件的 JDK 次版本号。

Class 文件的第 7 - 8 个字节代表了 Class 文件的主版本号(Major Version),即编译该 Class 文件的 JDK 主版本号。

高版本的 JDK 能向下兼容以前笨笨的 Class 文件,但不能运行新版本的 Class 文件。例如一个 Class 文件是使用 JDK 1.5 编译的,那么我们可以用 JDK 1.7 虚拟机运行它,但不能用 JDK 1.4 虚拟机运行它。下表列出了各个版本 JDK 的十六进制版本号信息:

从 HelloWorld 看 Java 字节码文件结构

我们看看之前的 Demo 文件的 Class 文件,其前 8 个字节分别是:cafe babe 0000 0034。那么我们可以知道,这个 Class 文件是由 JDK1.8 编译的。

常量池

Class 文件的第 9 - 10 个字节用于表示常量池常量的个数(constant_pool_count),那么紧跟着就有 constant_pool_count - 1 个常量。我们Class 文件第 9 - 10 个字节为 001d,表示有 28 个常量。

每个常量池的常量都用一个类型为 cp_info 的表表示,该表有 14 个值,分别是:

从 HelloWorld 看 Java 字节码文件结构

第 1 个常量。紧接着 001d 的后一个字节为 0A,表示该常量为方法引用类型(CONSTANT_MethodHandle_info)的常量。从上面的总表查阅知道,该常量项第 2 - 3 个字节表示类信息,这里是 0006 表示指向常量池第 6 个常量所表示的信息。该常量项的第 4 - 5 个字节表示名称及类描述符,这里值为 000f 表示指向常量池第 10 个常量所表示的信息。

第 2 个常量。紧接着 000f 的后一个字节为 09,表示该常量为字段引用类型(CONSTANT_Fieldref_info)的常量。从上面的总表查阅知道,该常量项第 2 - 3 个字节表示类信息,这里是 0010 表示指向常量池第 16 个常量所表示的信息。该常量项的第 4 - 5 个字节表示名称及类描述符,这里值为 0011 表示指向常量池第 17 个常量所表示的信息。

第 3 个常量。紧接着 0011 的后一个字节为 08,表示该常量为字符串引用类型(CONSTANT_String_info)的常量。从上面的总表查阅知道,该常量项第 2 - 3 个字节表示指向字符串字面量的索引,这里是 0012 表示指向常量池的第 18 个常量。

第 4 个常量。紧接着 0012 的后一个字节为 0A,表示该常量为方法引用类型(CONSTANT_MethodHandle_info)的常量。从上面的总表查阅知道,该常量项第 2 - 3 个字节表示类信息,这里是 0013 表示指向常量池第 19 个常量所表示的信息。该常量项的第 4 - 5 个字节表示名称及类描述符,这里值为 0014 表示指向常量池第 20 个常量所表示的信息。

第 5 个常量,是类信息类型常量,其指向了常量池第 21 个常量。

第 6 个常量,是类信息类型常量,其指向了常量池第 22 个常量。

第 7 个常量。这里表示 tag 的值是 01,表示该常量为一个字符串(CONSTANT_Utf8_info)的常量。从上面的总表查阅知道,该常量项第 2 - 3 个字节表示该字符串的长度,这里是 0006 表示该字符串长度为 6 个字节。这里紧接着 01 的六个字节为 3C 69 6E 69 74 3E。在 Class 文件中,字符串是使用 ASCII 码进行编码的,我们将这些十六进制字符转换成对应的 ASCII 码之后,其值为:<init>。

第 8 个常量,是一个字符串常量,转换之后是:()V。

第 9 个常量,是一个字符串常量,转换之后是:Code。

第 10 个常量,是一个字符串常量,转换之后是:LineNumberTable。

第 11 个常量,是一个字符串常量,转换之后是:main。

第 12 个常量,是一个字符串常量,转换之后是:([Ljava/lang/String;)V。

第 13 个常量,是一个字符串常量,转换之后是:SourceFile。

第 14 个常量,是一个字符串常量,转换之后是:Demo.java。

第 15 个常量。这里表示 tag 的值是 0C,表示该常量为方法引用类型(CONSTANT_NameAndType_info)的常量。从上面的总表查阅知道,该常量项第 2 - 3 个字节表示字段或方法名的索引,这里是 0007 表示指向常量池第 7 个常量所表示的信息。该常量项的第 4 - 5 个字节表示字段或方法描述符的索引,这里值为 0008 表示指向常量池第 8 个常量所表示的信息。根据我们之前的分析,可以知道第 15 个常量表示的信息其实是:"<init>":()V。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/83120d53324f0383eb6b0ceed8807a94.html