Java类文件 魔数与Class文件的版本

Java类文件是以字节流的形式存储的,其中前4个字节被称为魔数(Magic Number)。魔数的值为0xCAFEBABE,它是Java类文件的标识符,用于表示该文件是否为Java类文件。如果文件的前4个字节不是0xCAFEBABE,则不是Java类文件。

Java类文件的版本信息包括两个部分:主版本号和次版本号。主版本号用于表示JDK的版本,而次版本号用于表示该版本中的更新信息。Java类文件的版本号存储在类文件的头部,并且与类文件的格式版本号相关联。每个Java虚拟机实现都支持一组类文件格式版本。如果类文件的版本号超出了虚拟机的范围,则虚拟机将无法读取该类文件。

下面是一个示例Java类文件的头部,包括魔数和版本号信息:

CA FE BA BE 00 00 00 34 // 魔数和版本号
00 4D 0A 00 03 00 16 07
00 17 07 00 18 07 00 19
01 00 06 3C 69 6E 69 74
3E 01 00 03 28 29 56 01

在这个示例中,魔数为0xCAFEBABE,主版本号为0x00,次版本号为0x34,即Java SE 8。

Java类文件的魔数是指文件开头4个字节的值,它的值为十六进制数0xCAFEBABE。如果一个文件不符合这个规定,那么它就不是Java类文件,虚拟机在读取它时也会抛出异常。

Java类文件的版本部分,占据了整个Class文件的8个字节,它记录了类文件的版本号。这个版本号包含了2个部分,主版本号和次版本号。Java虚拟机根据这个版本号来决定是否支持读取这个类文件。

在Java SE 14及之前的版本中,Java类文件的版本号如下所示:

主版本号次版本号Java SE
453JDK 1.1
460JDK 1.2
470JDK 1.3
480JDK 1.4
490JDK 5
500JDK 6
510JDK 7
520JDK 8
530JDK 9
540JDK 10
550JDK 11
560JDK 12
570JDK 13
580JDK 14

在Java SE 15及之后的版本中,Java类文件的版本号如下所示:

主版本号次版本号Java SE
590JDK 15
600JDK 16
610JDK 17
620JDK 18

Java类文件的版本号可以通过javap命令来查看,例如:

$ javap -verbose MyClass
Classfile /Users/xxx/MyClass.class
  Last modified 2022-02-19; size 403 bytes
  SHA-256 checksum 96ca59fd1059b9c2b0f98cbbfa13930a417b7c8d61b46a7a42331d0e91f9bb3c
  Compiled from "MyClass.java"
public class MyClass
  minor version: 0
  major version: 59
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #2 // MyClass
  super_class: #3 // java/lang/Object
  interfaces: 0
  fields: 0
  methods: 2
    #1 // "<init>": "()V"
      ...
    #4 // main: "([Ljava/lang/String;)V"
      ...

这个例子中,Java类文件的主版本号是59,次版本号是0,表示这个类是在JDK 15环境下编译的。