使用 UE 打开 class 文件,第一行内容:
00000000h: CA FE BA BE 00 00 00 32 00 A9 07 00 02 01 00 37 ; 漱壕...2.?....7
前四个字节为固定的 CA FE BA BE ,接下来的四个字节为次版本号(0000)和主版本号(0032)。
33:JDK1.7
32:JDK1.6
31:JDK1.5
30:JDK1.4
2F:JDK1.3
2E: JDK1.2
2D: JDK1.1
java的class文件的头8个字节为:"magic"+"minor_version"+"major_version",即分别为文件类型(魔数)、文件格式次版本号、主版本号,这8个字节以16进制表示,每两位构成一个字节:
(1) magic: class文件的前4个字节为它的魔数(magic number):0xCAFEBABE。魔数的作用在于辨别是否为class文件(class文件必然是以0xCAFEBABE开头的);
(2) minor_verxion和major_version: class文件的下面4个字节便是次、主版本号。java虚拟机在读取class文件时会判断它的主次版本号,当其版本号超过它能处理的范围时,java虚拟机将不会处理该class文件,例如低版本的虚拟机无法执行高版本虚拟机编译的class文件。
//一段小代码 import java.io.FileInputStream; public class JavaVersionUtil { private static final String str = "C:/Users/Administrator/Desktop/DBUtil.class"; // 版本号对应: // 5.0 // 版本号(version):49.0 // 6.0 // 版本号(version):50.0 // 1.4 // 版本号(version):46.0 // 1.3 // 版本号(version):45.3 public static void main(String args[]) { try { // 读取文件数据,文件是当前目录下的First.class FileInputStream fis = new FileInputStream(str); int length = fis.available(); // 文件数据 byte[] data = new byte[length]; // 读取文件到字节数组 fis.read(data); // 关闭文件 fis.close(); // 解析文件数据 parseFile(data); } catch (Exception e) { System.out.println(e); } } private static void parseFile(byte[] data) { // 输出魔数 System.out.print("魔数(magic):0x"); System.out.print(Integer.toHexString(data[0]).substring(6) .toUpperCase()); System.out.print(Integer.toHexString(data[1]).substring(6) .toUpperCase()); System.out.print(Integer.toHexString(data[2]).substring(6) .toUpperCase()); System.out.println(Integer.toHexString(data[3]).substring(6) .toUpperCase()); // 主版本号和次版本号码 int minor_version = (((int) data[4]) << 8) + data[5]; int major_version = (((int) data[6]) << 8) + data[7]; System.out.println("版本号(version):" + major_version + "." + minor_version); } }
JDK 编译器版本 | target 参数 | 十六进制 minor.major | 十进制 minor.major |
jdk1.1.8 | 不能带 target 参数 | 00 03 00 2D | 45.3 |
jdk1.2.2 | 不带(默认为 -target 1.1) | 00 03 00 2D | 45.3 |
jdk1.2.2 | -target 1.2 | 00 00 00 2E | 46.0 |
jdk1.3.1_19 | 不带(默认为 -target 1.1) | 00 03 00 2D | 45.3 |
jdk1.3.1_19 | -target 1.3 | 00 00 00 2F | 47.0 |
j2sdk1.4.2_10 | 不带(默认为 -target 1.2) | 00 00 00 2E | 46.0 |
j2sdk1.4.2_10 | -target 1.4 | 00 00 00 30 | 48.0 |
jdk1.5.0_11 | 不带(默认为 -target 1.5) | 00 00 00 31 | 49.0 |
jdk1.5.0_11 | -target 1.4 -source 1.4 | 00 00 00 30 | 48.0 |
jdk1.6.0_01 | 不带(默认为 -target 1.6) | 00 00 00 32 | 50.0 |
jdk1.6.0_01 | -target 1.5 | 00 00 00 31 | 49.0 |
jdk1.6.0_01 | -target 1.4 -source 1.4 | 00 00 00 30 | 48.0 |
jdk1.7.0 | 不带(默认为 -target 1.6) | 00 00 00 32 | 50.0 |
jdk1.7.0 | -target 1.7 | 00 00 00 33 | 51.0 |
jdk1.7.0 | -target 1.4 -source 1.4 | 00 00 00 30 | 48.0 |
Apache Harmony 5.0M3 | 不带(默认为 -target 1.2) | 00 00 00 2E | 46.0 |
Apache Harmony 5.0M3 | -target 1.4 | 00 00 00 30 | 48.0 |