Java跨版本开发

跨版本 Java 开发的必要性

  • 兼容性需要,现有服务器只支持较老版本 Java,只好继续支持遗留的系统

最近接了一个程序开发项目,程序运行的服务器为window server 2003,32位操作系统。当时看到这个版本,差点没把一口血吐出来。

这个项目好在测试到最后,操作系统支持jdk1.8初始版本。这样可以使用新的jdk指定低版本1.8的java api代码风格完成代码编写,再使用1.8初始版本的javac和jar去编译与打包成目标jar包,并提交操作系统运行。

  • 可移植性需要

虽然java的代码编译一次之后,可以在任何java虚拟机上面运行,但是新的编译器编译出来的代码会有一个最低的可运行jre版本指定,如果java启动的时候,这个条件不满足,则会报最低java不满足条件的报错,并退出运行。比如这个项目,生产运行的是1.6,而大部分jar最低到1.8版本可运行,则需要重新使用javac1.6重新编译并打包,如果有多版本开发,则修改一个参数即可完成编译打包,代码修改量比较少。

多JDK所涉及的层面

开发层面

编写代码的过程,其实跟版本无关,主要是要考虑到用哪个版本的javac编译而用哪个级别的代码风格来编写代码,另外编写代码所用的工具链运行JDK版本,如lint工具所需要的代码级别、智能代码提示所需要的代码级别和jdk代码库,尽可能使用低级别的代码风格来编写jar库,这样才能支持更多的运行环境,编写完成之后,直接指定最低的运行级别,这里建议与大部分jar库一致指定最低1.8。

编译运行层面

运行需要指定相应级别的JDK/JRE来运行代码字节码,并且,程序所依赖的jar库需要满足最低运行级别,否则会报所运行的级别不支持。在这个层面基本只涉及javac和java程序,即相应JDK版本的javac和java,前者负责编译,后面负责运行。

编译打包层面

代码编写完成之后,打包成对应的jar/war包,编译依赖于javac的版本,打包依赖于jar.exe的版本,但打包理论上应该跟版本无关,jar包只是一个带了元数据的压缩包而已。

如何实现跨版本编译和打包

由于习惯使用maven这个工具来管理程序依赖并进行编译与打包,以下都是maven的案例。

  • 准备多个不同版本的 JDK

比如1.5、1.6、1.8、11、17等等,比如我的环境就有这么多个版本

  • 准备好toolchains.xml,并把它放到~/.m2/toolchains.xml,内容如下
<?xml version="1.0" encoding="UTF-8"?>
<toolchains>
 <!-- JDK toolchains -->
 <toolchain>
   <type>jdk</type>
   <provides>
     <version>1.6</version>
     <vendor>sun</vendor>
   </provides>
   <configuration>
     <jdkHome>C:\Users\wisfern\.jdks\jdk1.6.0_45_32</jdkHome>
   </configuration>
 </toolchain>
 <toolchain>
   <type>jdk</type>
   <provides>
     <version>1.8</version>
     <vendor>sun</vendor>
   </provides>
   <configuration>
     <jdkHome>C:\Users\wisfern\.jdks\jdk1.8.0_202_32</jdkHome>
   </configuration>
 </toolchain>
</toolchains>

有多少个jdk,就准备多少项toolchain,这里只准备两个,是因为其他更高级别的版本,暂时没遇到使用的地方。

  • 在 pom.xml 文件中设置编译器级别
    <properties>
       <java.version>1.8</java.version>
       <maven.compiler.source>1.6</maven.compiler.source>
       <maven.compiler.target>1.6</maven.compiler.target>
       <maven.toolchain.jdk.version>1.6</maven.toolchain.jdk.version>
   </properties>

   <build>
       <plugins>
           <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-toolchains-plugin</artifactId>
               <version>3.1.0</version>
               <executions>
                   <execution>
                       <goals>
                           <goal>toolchain</goal>
                       </goals>
                   </execution>
               </executions>
               <configuration>
                   <toolchains>
                       <jdk>
                           <version>${maven.toolchain.jdk.version}</version>
                           <vendor>sun</vendor>
                       </jdk>
                   </toolchains>
               </configuration>
           </plugin>
       </plugins>
   </build>

<java.version> 指定用于编译和运行该项目的 Java 版本。在这种情况下,它设置为 1.8。 <maven.compiler.source> 指定用于编译源代码的语言级别。这里,它设置为 1.6,这意味着代码必须与 Java 6 语法兼容。 <maven.compiler.target> 指定编译后的代码应兼容的 Java 字节码版本。这里也设置为 1.6,这意味着编译后的代码应该可以在 Java 6 运行时环境上运行。 <maven.toolchain.jdk.version> 指定构建项目时要使用的 JDK 版本。在这里,它设置为 1.6,这意味着构建应该使用 JDK 6,并且这个参数在maven-toolchains-plugin插件引用,设置了插件所调用的编译与打包工具链。

  • 做完以上就可以操作
maven package -X

-X 启用更详细的日志输出,这样就可以在日志看到所调用的javac和jar的路径。

兼容性问题处理

unsupport class version

  • 版本间兼容性问题
  • 升级 Java 版本带来的应用程序修改
  • 使用第三方库时的版本兼容性问题

参考资料

  1. https://maven.apache.org/guides/mini/guide-using-toolchains.html

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

Scroll to Top