Java class文件的JDK编译版本号

时间:2022-04-12 17:19:40

JDK版本:1.7

E:\>javac -source 1.5 -target 1.5 TsLog.java -encoding utf-8

编译出的目标版本(class文件版本)为1.5,版本编码31

E:\>javac -source 1.5 -target 1.6 TsLog.java -encoding utf-8

编译出的目标版本(class文件版本)为1.6,版本编码32

E:\>javac -source 1.5 -target 1.7 TsLog.java -encoding utf-8

编译出的目标版本(class文件版本)为1.7,版本编码33

00000000h: CA FE BA BE 00 00 00 33 00 2C 0A 00 08 00 24 09 ; 漱壕...3.,....$.

E:\>javac -source 1.6 -target 1.6 TsLog.java -encoding utf-8

编译出的目标版本(class文件版本)为1.6,版本编码32

E:\>javac -source 1.7 -target 1.6 TsLog.java -encoding utf-8
javac: 源发行版 1.7 需要目标发行版 1.7

目标版本高于源版本,不能编译





---------------------------------------------

Java class文件的JDK编译版本号

需要用可打开二进制文件的软件来打开,不要用文本方式打开或其他文本编辑器打开。
  比如用UltraEdit(UE)打开class文件(如果是在linux,比如Ubuntu下,用$hexdump -C Test.class),你会看到诸如第一行是:

  00000000h: CA FE BA BE00 00 32 00 A9 07 00 02 01 00

 前四个字节为固定的 CA FE BA BE,接下来的四个字节为次版本号(0000)和主版本号(0032)。
 33:JDK1.7
 32:JDK1.6
 31:JDK1.5
 30:JDK1.4
 2F:JDK1.3
Java class文件的JDK编译版本号




附更详细的《 飞鸟blog JDK Class 版本识别表 》:

现在不妨从 JDK 1.1 到 JDK 1.7 编译器编译出的 class 的默认 minor.major version吧。(又走到 Sun 的网站上翻腾出我从来都没用过的古董来)

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

上面比较是 Windows 平台下的 JDK 编译器的情况,我们可以此作些总结:

1) -target 1.1 时 有次版本号,target 为 1.2 及以后都只用主版本号了,次版本号为 0
2) 从 1.1 到 1.4 语言差异比较小,所以 1.2 到 1.4 默认的 target 都不是自身相对应版本
3) 1.5 语法变动很大,所以直接默认 target 就是 1.5。也因为如此用 1.5 的 JDK 要生成目标为 1.4的代码,光有 -target 1.4 不够,必须同时带上 -source 1.4,指定源码的兼容性,1.6/1.7 JDk 生成目标为1.4 的代码也如此。
4) 1.6 编译器显得较为激进,默认参数就为 -target 1.6。因为 1.6 和 1.5 的语法无差异,所以用 -target1.5 时无需跟着 -source 1.5。
5) 注意 1.7 编译的默认 target 为 1.6
6) 其他第三方的 JDK 生成的 Class 文件格式版本号同对应 Sun 版本 JDK
7) 最后一点最重要的, 某个版本的 JVM 能接受class 文件的最大主版本号不能超过对应 JDK 带相应 target 参数编译出来的 class文件的版本号

上面那句话有点长,一口气读过去不是很好理解,举个例子:1.4 的 JVM 能接受最大的 class 文件的主版本号不能超过用 1.4JDK 带参数 -target 1.4 时编译出的 class 文件的主版本号,也就是 48。

因为 1.5 JDK 编译时默认 target 为 1.5,出来的字节码 major.minor version 是 49.0,所以1.4 的 JVM 是无法接受的,只有抛出错误。

那 么又为什么从 1.1 到 1.2、从 1.2 到 1.3 或者从 1.3 到 1.4 的 JDK 升级不会发生Unsupported major.minor version 的错误呢,那是因为 1.2/1.3/1.4都保持了很好的二进制兼容性,看看 1.2/1.3/1.4 的默认 target 分别为 1.1/1.1/1.2就知道了,也就是默认情况下1.4 JDK 编译出的 class 文件在 JVM 1.2 下都能加载执行,何况于 JVM 1.3呢?(当然要去除使用了新版本扩充的 API 的因素)

转载自:https://blog.csdn.net/hongweigg/article/details/52598995