Java 是跨平台的,JVM 作为中间层,自然要针对不同的操作系统提供不同的实现。
通过不同操作系统的 JVM,源代码就可以不用根据不同的操作系统编译成不同的二进制可执行文件了,跨平台的目标也就实现了。那这个 class 文件到底是什么玩意呢?它是怎么被 JVM 识别的呢?
编写一段简单的 Java 代码,文件名为 Hello.java。
package com.fcant.jvm;
class Hello {
public static void main(String[] args) {
System.out.println("Hello!");
}
}
点击编译按钮后,IDEA 会自动生成一个名为 Hello.class 的文件,在 target/classes
的对应包目录下。直接双击打开后长下面这样子:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.fcant.jvm;
class Hello {
Hello() {
}
public static void main(String[] args) {
System.out.println("Hello!");
}
}
看起来和源代码很像,只是多了一个空的构造方法,它是 class 文件被 IDEA 自带的反编译工具 Fernflower 反编译后的样子。那真实的 class 文件长什么样子呢?
可以在 terminal 面板下用 xxd Hello.class
命令来查看。
它是 class 文件的一种十六进制形式,xxd
这个命令的神奇之处就是它能将一个给定文件转换成十六进制形式。
1、魔数
第一行中有一串特殊的字符 cafebabe
,它就是一个魔数,是 JVM 识别 class 文件的标志,JVM 会在验证阶段检查 class 文件是否以该魔数开头,如果不是则会抛出 ClassFormatError
。
魔数 cafebabe
的中文意思显而易见——咖啡,再加上 Java 的图标本来就是一个热气腾腾的咖啡,可见 Java 与咖啡的渊源有多深。
2、版本号
紧跟着魔数后面的四个字节 0000 0037
分别表示副版本号和主版本号。也就是说,主版本号为 55(0x37 的十进制),也就是 Java 11 对应的版本号,副版本号为 0。
上一个 LTS 版本是 Java 8,对应的主版本号为 52,也就是说 Java 9 是 53&#