1. Introduction
1.介绍
One of the new features that Java 9 brings us is the capability to build Multi-Release JARs (MRJAR). As the JDK Enhancement Proposal says, this allows us to have different Java release-specific versions of a class in the same JAR.
Java 9 为我们带来的新功能之一是能够构建多版本 JAR(MRJAR)。正如JDK 增强建议所述,这使我们能够在同一个 JAR 中拥有不同的 Java 版本的特定类。
In this tutorial, we explore how to configure an MRJAR file using Maven.
在本教程中,我们将探讨如何使用Maven配置MRJAR文件。
2. Maven
2.Maven
Maven is one of the most used build tools in the Java ecosystem; one of its capabilities is packaging a project into a JAR.
Maven是Java生态系统中最常用的构建工具之一;其功能之一是将项目打包成JAR。
In the following sections, we’ll explore how to use it to build an MRJAR instead.
在下面的章节中,我们将探讨如何使用它来建立一个MRJAR。
3. Sample Project
3.项目样本
Let’s start with a basic example.
让我们从一个基本的例子开始。
First, we’ll define a class that prints the Java version currently used; before Java 9, one of the approaches that we could use was the System.getProperty method:
首先,我们要定义一个能打印当前使用的Java版本的类;在Java 9之前,我们可以使用的方法之一是System.getProperty方法。
public class DefaultVersion {
public String version() {
return System.getProperty("java.version");
}
}
Now, from Java 9 and onward, we can use the new version method from the Runtime class:
现在,从Java 9开始,我们可以使用来自Runtime类的新version方法。
public class DefaultVersion {
public String version() {
return Runtime.version().toString();
}
}
With this method, we can get a Runtime.Version class instance that gives us information about the JVM used in the new version-string scheme format.
通过这个方法,我们可以得到一个Runtime.Version类实例,它为我们提供了新版本字符串计划格式中使用的JVM信息。
Plus, let’s add an App class to log the version:
另外,让我们添加一个App类来记录版本。
public class App {
private static final Logger logger = LoggerFactory.getLogger(App.class);
public static void main(String[] args) {
logger.info(String.format("Running on %s", new DefaultVersion().version()));
}
}
Finally, let’s place each version of DefaultVersion into its own src/main directory structure:
最后,让我们把每个版本的DefaultVersion放入自己的src/main目录结构中。
├── pom.xml
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── baeldung
│ │ │ └── multireleaseapp
│ │ │ ├── DefaultVersion.java
│ │ │ └── App.java
│ │ └── java9
│ │ └── com
│ │ └── baeldung
│ │ └── multireleaseapp
│ │ └── DefaultVersion.java
4. Configuration
4.配置
To configure the MRJAR from the classes above, we need to use two Maven plugins: the Compiler Plugin and the JAR Plugin.
为了配置上述类的MRJAR,我们需要使用两个Maven插件:Compiler Plugin和JAR Plugin。
4.1. Maven Compiler Plugin
4.1.Maven Compiler Plugin
In the Maven Compiler Plugin, we need to configure one execution for each Java version we’ll package.
在Maven编译器插件中,我们需要为我们要打包的每个Java版本配置一个执行。
In this case, we add two:
在这种情况下,我们增加两个。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>compile-java-8</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</execution>
<execution>
<id>compile-java-9</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<release>9</release>
<compileSourceRoots>
<compileSourceRoot>${project.basedir}/src/main/java9</compileSourceRoot>
</compileSourceRoots>
<outputDirectory>${project.build.outputDirectory}/META-INF/versions/9</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
We’ll use the first execution compile-java-8 to compile our Java 8 class and the compile-java-9 execution to compile our Java 9 class.
我们将使用第一个执行compile-java-8来编译我们的Java 8类,使用compile-java-9执行来编译我们的Java 9类。
We can see that it’s necessary to configure the compileSourceRoot and outputDirectory tags with the respective folders for the Java 9 version.
我们可以看到,有必要将compileSourceRoot和outputDirectory标签配置为Java 9版本的相应文件夹。
However, as of maven-compiler-plugin 3.7.1, we don’t need to set the output directory manually. Instead, all we have to do is to enable the multiReleaseOutput property:
然而,从maven-compiler-plugin3.7.1>开始,我们不需要手动设置输出目录。相反,我们要做的就是启用multiReleaseOutput属性。
<configuration>
<release>9</release>
<compileSourceRoots>
<compileSourceRoot>${project.basedir}/src/main/java9</compileSourceRoot>
</compileSourceRoots>
<multiReleaseOutput>true</multiReleaseOutput>
</configuration>
When set to true, the compiler plugin moves all release-specific classes to the META-INF/versions/${release} directory. Please note that we have to set the release tag to the desired Java version here, otherwise the compiler plugin fails.
当设置为true时,编译器插件会将所有特定于发行版的类转移到META-INF/versions/${release}目录。目录。请注意,我们必须在这里将release 标签设置为所需的Java版本,否则编译器插件会失败。
4.2. Maven JAR Plugin
4.2.Maven JAR插件
We use the JAR plugin to set the Multi-Release entry to true in our MANIFEST file. With this configuration, the Java runtime will look inside the META-INF/versions folder of our JAR file for version-specific classes; otherwise, only the base classes are used.
我们使用JAR插件在我们的MANIFEST文件中把Multi-Release项设置为true。有了这个配置,Java运行时将在我们的JAR文件的META-INF/versions文件夹中寻找特定版本的类;否则,只使用基类。
Let’s add the maven-jar-plugin configuration:
我们来添加maven-jar-plugin配置。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifestEntries>
<Multi-Release>true</Multi-Release>
</manifestEntries>
</archive>
</configuration>
</plugin>
5. Testing
5.测试
It’s time to test our generated JAR file.
现在是时候测试我们生成的JAR文件了。
When we execute with Java 8, we’ll see the following output:
当我们用Java 8执行时,我们会看到以下输出。
[main] INFO com.baeldung.multireleaseapp.App - Running on 1.8.0_252
But if we execute with Java 14, we’ll see:
但如果我们用Java 14执行,我们会看到。
[main] INFO com.baeldung.multireleaseapp.App - Running on 14.0.1+7
As we can see, now it’s using the new output format. Note that although our MRJAR was built with Java 9, it’s compatible with multiple major Java platform versions.
正如我们所看到的,现在它正在使用新的输出格式。注意,尽管我们的MRJAR是用Java 9构建的,但它与多个主要的Java平台版本兼容。
6. Conclusion
6.结论
In this brief tutorial, we saw how to configure the Maven build tool to generate a simple MRJAR.
在这个简短的教程中,我们看到了如何配置Maven构建工具来生成一个简单的MRJAR。
As always, the full code presented in this tutorial is available over on GitHub.
一如既往,本教程中介绍的完整代码可在GitHub上获得over。