我们在做dubbo接口开发是,要考虑jdk版本兼容的问题。如果是高版本的jre运行低版本jdk compile 的jar,根据java的向下兼容性,这个没有问题。但如果是低版本jre运行高版本的jdk compile的jar,会怎么样呢?
问题的背景
最近在做项目时,由于要用到elastichsearch 做开发,elastichsearch 的jdk版本是java7,而公司要求的java版本一般来说是java6,当时想java7 的jre可以运行java6 compile的jar包,应该没有什么问题。后来在发布duboo接口到maven私库上时,发现问题了,如果用java7 compile jar 包到maven私库上,调用方如果使用的是java6,能正常运行吗?在和同事讨论时,大体上有两种观点
* 如果没有使用java7 的 feature,则java1.6的jre可以运行jdk1.7 compile 的jar包
* java1.6不能运行java7 compile 的jar包
到底哪种说法是正确的呢?
看看官方文档怎么说
我从oracle 找到了一份java8 compatible document
Binary Compatibility
Java SE 8 is binary-compatible with Java SE 7 except for the incompatibilities listed below. Except for the noted incompatibilities, class files built with the Java SE 7 compiler will run correctly in Java SE 8. Class files built with the Java SE 8 compiler will not run on earlier releases of Java SE.
官方文档的意思是:同一份代码,用java8打包的jar,不能在java7上运行,反之可以。
那我们来试一试吧,看java7打包jar, mvn clean install 到本地 ,然后,用另外一个项目来调用,会怎么样?
我们启动一个调用方的项目
StagePayBusinessTO : Unsupported major.minor version 51.0
程序在运行时报错了
所以,我们得出一个结论,高版本编译的java代码,在低版本无法运行.那么,现在另外一个问题来了,如果项目的jdk是java7的,但jsf接口的API必须是java6的,如果哪天不小心,mvn deploy时用java7的编译打包后传到了maven私库上,调用方如果使用的是jre1.6的版本,当下载你的高版本编译的依赖jar包后,直接导致程序无法启动,这个怎么办呢?
重新认识maven-compiler-plugin 插件
笔者之前,一直认为configuration的source,target中的数值是约束jdk版本的,只要本地jdk版本大于等于这个数值就行。比如,这个数值是1.6,那么只要jdk版本大于等于1.6,就可以编译,如果jdk版本是1.7,则是生成的是jdk1.7规范的class文件,如果jdk是1.6,则生成的是jdk1.6规范的class文件。笔者认真看了一下这个插件的文档,发现source和target是javac 在编译时要传的参数。我在官方网站上找到了关于source和target的说明,source不用介绍了,我们重点看一下target的说明。
-target version Generate class files that target a specified version of the VM. Class files will run on the specified target and on later versions, but not on earlier versions of the VM. Valid targets are 1.1, 1.2, 1.3, 1.4, 1.5 (also 5), 1.6 (also 6), and 1.7 (also 7).
The default for -target depends on the value of -source:
If -source is not specified, the value of -target is 1.7
If -source is 1.2, the value of -target is 1.4
If -source is 1.3, the value of -target is 1.4
If -source is 1.5, the value of -target is 1.7
If -source is 1.6, the value of -target is 1.7
For all other values of -source, the value of -target is the value of -source.
从以上说明中我们可以看出,target配置多少,就用哪个jdk版本的规范文件。比如,你是java7的编译器,如果target是1.6,则生成java1.6规范的class文件。 有了这个插件,我们在jsf 接口发布的时候,只需要在API 子项目的pm.xml中配置好1.6,就可以了,再也不用担心因为是java1.7的编译器而把JSF接口的jar 编译成java1.7规范的class了。