本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
转载自夜明的孤行灯
本文链接地址: https://www.huangyunkun.com/2018/03/10/java-9-multi-release-jar-files/
Java 9的特性有一个标号238的特性,链接如下:JEP 238: Multi-Release JAR Files
这个特性是有一定争议的,并没有在开源框架中大规模使用。
简而言之,多版本jar允许打包同一个类的多个版本,供不同运行时使用。 例如,如果在JDK 8上运行,Java运行时将使用该类的Java 8版本,但如果在Java 9上运行,它将使用Java 9特定的实现。同样,如果为Java 10版本构建版本,则运行时将使用它来代替Java 9和默认(Java 8)版本。
多版本JAR的用例
优化的运行时间
开发应用程序时,开发人员不知道将在哪个运行时执行。 但是对于某些运行时,可以实现相同类的优化版本。 例如通过查看java.version可以判断当前运行环境,然后通过一些技术手段来调用不同的实现。多版本Jar可以直接从JVM层提供这种特性的支持,不再需要自己实现。
冲突的API
例如需要支持2个不同的运行时,但有一个已弃用的API。 目前有两种广泛使用的解决方案:
最直接的方法是使用反射。 例如,可以定义一个VersionProvider接口,然后定义2个具体的类Java8VersionProvider和Java9VersionProvider ,它们是在运行时加载。 这个解决方案的一个变体是只有一个类,但是有不同的方法,通过反射访问和调用不同的方法。
如果技术上适用,更高级的解决方案是使用方法句柄。
还有一种常见的方案就是直接提供两个不同的jar文件,比如guava-jdk8和guava-jdk9。这个方法简单有效,但是管理这种代码库会带来一些难度。
多版本JAR的使用
Multi-release JAR files的关键在于MANIFEST.MF中,首先要声明
Multi-Release: true
然后提供不同版本的class文件,大概目录如下
Gradle作为常见的JVM平台项目构建工具,虽然目前没有对于多版本Jar的直接支持,但是由于灵活性大,可以直接自动配置一个。
首先是生成jar阶段
jar { into('META-INF/versions/9') { from sourceSets.java9.output } manifest.attributes( 'Multi-Release': 'true' ) }
其次就是测试阶段,因为提供了多版本Jar,所以测试也应该有所针对
test { dependsOn jar def jdkHome = System.getenv("JAVA_8") classpath = files(jar.archivePath, classpath) - sourceSets.main.output executable = file("$jdkHome/bin/java") doFirst { println "$name runs test using JDK 8" } } task testJava9(type: Test) { dependsOn jar def jdkHome = System.getenv("JAVA_9") classpath = files(jar.archivePath, classpath) - sourceSets.main.output executable = file("$jdkHome/bin/java") doFirst { println classpath.asPath println "$name runs test using JDK 9" } } check.dependsOn(testJava9)
如果需要JDK10的支持也是一样的。
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
转载自夜明的孤行灯
本文链接地址: https://www.huangyunkun.com/2018/03/10/java-9-multi-release-jar-files/