Multi-Release JARs in Java 9

While developing Java-based solutions, one would have to often include third party libraries to code better. These third-party libraries usually release different releases according to the support matrix they have. This would result in having different library versions targeted for different Java versions. As a result, it would be difficult to ensure that everything works seamlessly while upgrading the JDK version without executing the complete list of tests for a particular Java-based application. To overcome these shortcomings, a Java Enhancement Proposal (jep 238) was suggested so that JAR format is modified to accommodate multiple versions of same libraries which target different Java version in a single application jar. The correct variant of the library will be loaded at runtime depending on the java version. These new types of jar files are called Multi-Release JAR files.

How To Create A Multi-Release JAR?

Let us try a simple example to understand it better. As we all know, java 9 introduced the concept of modules. So, we will create simple program in which almost all code is same except the fact that we print the module name of StringBuilder only in the version that is intended for Java 9.

Create the following folder structure:

 

Multi release Jar tree structure

Create the following class under testproj-8:

Create the following class under testproj-9:

Compile the classes in respective folders using the command:

Navigate to the root folder and create the multi-release jar using the following command:

We can see a new jar is created under the same folder where we ran the command.

Inside The Multi-Release JAR

Using jar tvf command, we should be able to see the contents of the jar file:

Note that the class file intended for java 9 and above is placed inside META-INF/versions/9 folder. The class file which was created from source under testproj-8 is there in the root folder of the jar file.

If we inspect the MANIFEST.MF file after extracting the archive, we can see that Multi-release: true is added at the end of the file. This is a nice feature because if there is a change for version intended for java 10, we just have to update the jar structure by specifying – – release 10 and adding the newer implementations without breaking compatibility of our utility jar with old releases. Java versions prior to java 9 will consider only the StringBuilderDemo.class that is in the root folder and will be unaffected by the versions informatopm contained inside META-INF/versions folder.

Few Things To Note While Building A Multi-Release JAR

To explain the concept of multi-release jars, we had used simple examples in the previous sub-sections. There are certain things that should be kept in mind while working with Multi-Release JAR files.

  • If we specify any version number less than 9 or a string for the –release in command line, it will be discarded.
  • Earlier JDKs which do not support multi-release jars will see only the root folder of the jar. Hence it will be good to keep code which is compatible with java 8 or earlier in the root folder and specify the versions using –release for jdk versions from 9 onwards.
  • For a given .class file that has multiple versions, care should be taken to offer the same public API so that it supports backward compatibility. A public class present in release-specific folder should be present in the root folder as well. But it is not necessary to have separate versions for all the classes that are in the root folder. The versions can be added when required. Module based and JAR based class loaders will load the classes according to the version jdk in which the jars are run.
  • It is possible to create a signed multi-release jar file.
  • The Java Runtime’s Boot class loader does not support multi-release jar files. If such a jar is added to boot class path, then that jar is treated as a normal jar instead of a multi-release jar.

 

Modular Multi-release JAR Files

Modular multi-release jar files are those with module-info.class files included to define the respective modules in the library. Since versioned source’s class files are saved under META-INF/version/<versionNumber> folder, the module-info classes for the respective versions will be present in these areas.

There are few things which are worth noting about modular multi-release JARs:

  • It is possible to have different requires fields in each version’s module descriptor.
  • It is possible to have different clauses for the module descriptors for each JDK version.
  • It is possible to have a modular multi-release jar file with no module descriptors in the root folder. This ensures backward compatibility with Java 8 if the application jar is intended to be used in that JDK also because the root folder of the java archive file will resemble that of a normal jar.

Modular Multi-Release JAR Vs ModulePath And ClassPath

As mentioned previously, it is possible to construct a Modular Multi-Release JAR so that it works directly on class path of Java 8, classpath of Java 9 and module path of java 9. If some packages of the JAR are not exported in the module-info.class file, when the JAR is placed on the module path, it will result in not recognizing those omitted classes. This is a known problem that can occur while dealing with modular multi-release jar files as they are bound to support both classpath and module path to ensure backward compatibility with Java 8.

To combat the situation, when constructing a modular multi-release JAR file, if public API differences are detected as a result of module private classes being inaccessible when the JAR file is placed on the classpath, the jar tool prints a warning to the console output.

Summary

With the introduction of multi-release JARs in Java 9, developers who consume third party libraries need not upgrade their own JDK versions if the libraries are upgraded to support later versions of java. It makes life easier for third-party library developers as well by making sure that backward compatibility is provided. The need to support multiple versions of the libraries for multiple versions of java will no longer be there if the third party libraries/softwares are designed to be packaged as multi-release JARs.

2 thoughts to “Multi-Release JARs in Java 9”

Leave a Reply