起因
我把一堆 jar 包引入了某个 Service 工程,然后提交代码,并在 Jenkins 上构建-测试-部署。
结果:构建成功,测试抛异常。异常如下:
com/beust/jcommander/ParameterException : Unsupported major.minor version 52.0
经过
百度一下,典型的用高版本的JDK编译产生的class文件,用低版本的JDK运行这个class文件时产生的异常。说是由于使用 JDK 1.8 编译的 class 文件不能在低版本下使用的缘故,将运行环境改为 1.8 即可。
可,线上环境岂是说换就能换的,只能通过更换 jar 包来解决,那到底是哪个 jar 出现了问题呢?并不清楚。不过猜测应该是 jcommander 关联的 jar,可我并没引入 jcommander 呀,那就只能是别的 jar 引入了 jcommander 从而带到工程中了。然后,我就只能一一去尝试,单独引入再提交运行,看是否是引入的 jar 包有问题。最后发现,是引入了 TestNG 6.11 才引发的这个问题。将 TestNG 版本改为最新 6.13.1 再试,问题解决。
反思
可以说,上面的过程非常麻烦,在某些复杂的情况下,根本就没办法去实施。
二次解决
Google 一下,将“com/beust/jcommander/ParameterException : Unsupported major.minor version 52.0”整个复制到搜索栏搜索,意外的,前两个搜索结果及其相关:jdk7 user getting compile error when use testNG 6.11,打开之后,看到:
TestNG Version
6.11Expected behavior
TestNG should support jdk7Actual behavior
JDK7 user getting Unsupported major.minor version 52.0 when compile their code that depends on testNG 6.11.
Java complaining about com.beust:jcommander:1.64, that is a jdk8 only lib after v1.58 (or so).
可以说,正中下怀。直接修改 TestNG 版本号即可。可以看出,使用 Google 搜索问题,解决效率会高很多。
扩展
major.minor 到底是个什么玩意儿呢?
Wikipedia 上有篇介绍:Java class file,对 class 文件介绍的很清楚。
java 编译出的 class 文件结构包含 10 个基本部分:
Magic Number: 0xCAFEBABE
Version of Class File Format: the minor and major versions of the class file
Constant Pool: Pool of constants for the class
Access Flags: for example whether the class is abstract, static, etc.
This Class: The name of the current class
Super Class: The name of the super class
Interfaces: Any interfaces in the class
Fields: Any fields in the class
Methods: Any methods in the class
Attributes: Any attributes of the class (for example the name of the sourcefile, etc.)
可以看出,minor and major versions 组成了 class 文件基本部分之一的“Version of Class File Format”,应该翻译为“class文件格式版本”吧。至于版本号,minor version 和 major version 分别使用两个字节(16bits),其文章也有详细描述。
这里贴一下 major version 的版本号和 JDK 版本的对照:
Java SE 9 = 53 (0x35 hex),
Java SE 8 = 52 (0x34 hex),
Java SE 7 = 51 (0x33 hex),
Java SE 6.0 = 50 (0x32 hex),
Java SE 5.0 = 49 (0x31 hex),
JDK 1.4 = 48 (0x30 hex),
JDK 1.3 = 47 (0x2F hex),
JDK 1.2 = 46 (0x2E hex),
JDK 1.1 = 45 (0x2D hex).
我用 JDK7 编译了一个 class 文件,然后看一下文件内容:
看吧,版本号的部分就是在文件的这个位置。
嗯,就这样吧。
哦,对了,遇到问题先用百度搜,毕竟不用FQ。如果换了两次关键词还搜不出来那就用Google搜,不要马上用自己的蠢办法去尝试解决,太累。