Java 简明教程

Java - Multi-Release Jar Files

Multi-release JAR 功能是在 Java 9 中引入的。它允许使用与多个 Java 版本相关的多个类版本。例如,许多第三方库或框架使用 Java。由于 Java 作为一门语言在不断发展,并且在每次重大版本发布时,都会为该语言添加许多新功能。由于第三方库/框架必须重写其代码库才能适应新功能,因此团队非常不愿意使用新功能。它阻碍了它们向新的 versions of Java 迁移。

Multi-release JAR feature was introduced in Java 9. It allows to use of multiple versions of a class pertaining to multiple versions of Java. For example, many third-party libraries or frameworks use Java. As Java as a language is continuously evolving and with every major release, many new features are getting added to the language. As third-party libraries/frameworks have to rewrite their code base in order to accommodate new features, teams are highly reluctant to use the new features. It acts as a hindrance to them to move to the new versions of Java.

为了解决同一文件或平台特定文件版本的多个源代码的此维护问题,引入了多版本 JAR 特性。考虑以下示例:

In order to counter this problem of maintenance of multiple source codes of the same file or platform-specific version of a file, the Multirelease JAR feature was introduced. Consider the following example:

典型的 jar 文件在根级别具有所有类。

A typical jar file has all the classes at the root level.

jar root
   - Calculator.class
   - Util.class
   - Math.class
   - Service.class

如果我们具有 Java 9 特定功能 Util class ,则无法在 JRE 8 或更低版本中使用该 jar。

If we’ve Java 9 feature specific Util class then that jar cannot be used in JRE 8 or lower.

在多发布 JAR 中,格式得到了增强,能够存储不同的 Java classes 版本或资源,可以根据平台进行维护和使用。在 JAR 中,一个文件 MANIFEST.MF 文件在其主部分有一个条目 Multi-Release: true。META-INF 目录还包含一个版本子目录,其子目录(从 Java 9 的 9 开始)存储特定于版本的类和资源文件。

In multi-release Jar, the format has been enhanced to have different versions of Java classes or resources that can be maintained and used as per the platform. In JAR, a file MANIFEST.MF file has an entry Multi-Release: true in its main section. META-INF directory also contains a versions subdirectory whose subdirectories (starting with 9 for Java 9 ) store version-specific classes and resource files.

使用 MANIFEST.MF,我们可以在单独的位置指定 Java 9 或更高版本的特定类,如下所示:

Using MANIFEST.MF, we can specific Java 9 or higher version-specific classes in separate locations as shown below:

Java Multi-Release Jar Files Directory Structure

jar root
   - Calculator.class
   - Util.class
   - Math.class
   - Service.class
   META-INF
      - versions
      - 9
         - Util.class
         - Math.class
      - 10
         - Util.class
         - Math.class

现在,如果 JRE 不支持多发行 JAR,那么它将选择根级别类进行加载和执行,否则,将加载特定于版本的类。例如,如果在 Java 8 中使用了上述 JAR,那么将使用根级别的 Util.class。如果 Java 9 执行了相同的 JAR,那么将选择特定于 Java 9 版本的类,依此类推。通过这种方式,第三方库/框架可以在不更改针对较低版本编写的源代码的情况下支持新特性。

Now if JRE is not support Multi-release jar, then it will choose the root level classes to load and execute otherwise, version specific classes will be loaded. For example, if above jar is used in Java 8, then root level Util.class will be used. If same jar is executed by Java 9, then java 9 version specific class will be picked and so on. This way, third party libraries/frameworks can support new features without changing their source codes which was written targeting the lower versions.

Creating and Using Multi-Release Jar Files in Java

在此示例中,我们将创建并使用多版本 jar 来拥有两个版本的 Tester.java 文件,一个用于 jdk 7,一个用于 jdk 9,并在不同 jdk 版本上运行它。

In this example, we’ll be creating and using a multi-release jar to have two versions of Tester.java file, one for jdk 7 and one for jdk 9 and run it on different jdk versions.

以下是有关在 Java 中创建和使用多版本 jar 文件的步骤 -

The following are the steps for creating and using multi-release jar files in Java -

Step 1: Create Java 7 Specific Java Class

让我们创建一个 Java 类,它可能具有 Java 7 特定的代码和特性,在 Java 9 之前不可用。在此示例中,我们仅打印一条消息,以展示此特性的用法。

Let’s create a Java class that may have Java 7 specific code and features which is not available prior to Java 9. In this example, we’re simply printing a message just to showcase the usage of this feature.

创建一个文件夹 c:/test/java7/com/tutorialspoint。使用以下内容创建 Tester.java −

Create a folder c:/test/java7/com/tutorialspoint. Create Tester.java with following content −

Tester.java

这是一段简单的代码,在我们执行程序时,会打印一个 Java 7 特定的消息。

This is a simple code where we’re printing a Java 7 specific message when program is executed.

package com.tutorialspoint;

public class Tester {
   public static void main(String[] args) {
      System.out.println("Inside java 7");
   }
}

Step 2: Create Java 9 Specific Java Class

让我们创建一个 Java 类,它可能具有 Java 9 增强特性和特性,在 Java 9 之前不可用。在此示例中,我们仅打印一条消息,以展示此特性的用法。

Let’s create a Java class that may have code specific to Java 9 enhancements and features which is not available prior to Java 9. In this example, we’re simply printing a message just to showcase the usage of this feature.

创建一个文件夹 c:/test/java9/com/tutorialspoint。使用以下内容创建 Tester.java −

Create a folder c:/test/java9/com/tutorialspoint. Create Tester.java with following content −

Tester.java

这也是类似于上面的代码,在执行程序时会打印一个 Java 9 特定的消息。

This is also similar code as above where we’re printing a Java 9 specific message when program is executed.

package com.tutorialspoint;

public class Tester {
   public static void main(String[] args) {
      System.out.println("Inside java 9");
   }
}

为了使用多发布 jar 功能,我们必须确保两个类的签名相同。公共 interface ,如方法签名,在两个类中应该相同。

In order to use multi-release jar feature, we must ensure that signature of both class should be same. Public interface like method signatures should be same in both the classes.

Step 3: Compile with Target Versions

C:\test > javac --release 9 java9/com/tutorialspoint/Tester.java

C:\JAVA > javac --release 7 java7/com/tutorialspoint/Tester.java

Step 4: Create a Multi-Release JAR

C:\JAVA > jar -c -f test.jar -C java7 . --release 9 -C java9.
Warning: entry META-INF/versions/9/com/tutorialspoint/Tester.java,
   multiple resources with same name

Step 5: Run the JAR with JDK 7

C:\JAVA > java -cp test.jar com.tutorialspoint.Tester
Inside Java 7

Step 6: Run the JAR JDK 9

C:\JAVA > java -cp test.jar com.tutorialspoint.Tester
Inside Java 9

Conclusion

我们看到,使用多版本 Jar 特性,我们可以创建多个类版本而无需担心向后兼容性问题。我们展示了相同的命令可用于执行类。根据 META-INF 文件中列出的 JRE 版本,选择相应的类。对于不支持多版本 jar 的较低 JRE 版本,则选择根级别类而不是特定于版本的类。最后,带版本类的公共方法的签名应相同,这样此功能才能完美运行。

We can see, that with multi-release Jar feature, we can create multiple version of a class without having backwards compatibility issues. We’ve showcased that same command can be used to execute a class. Based on the JRE version listed in META-INF file, the corresponding class is picked. In case of lower JRE version which is not supporting Multi-Release jar, the root level classes are picked instead of version specific classes. And lastly, the signature of public methods of the versioned classes should be same so this functionality can work perfectly.