Java Multi-Release JAR Files: Version Compatibility Across Java Versions

Discover the Java Multi-Release JAR feature, introduced in Java 9, which allows developers to include multiple versions of a class within a single JAR file. This feature enables compatibility across different Java versions, making it valuable for third-party libraries and frameworks that support multiple Java environments.



Java Multi-Release Jar Files

The Multi-release JAR feature was introduced in Java 9. It allows you to use multiple versions of a class depending on the Java version. This feature is particularly useful for third-party libraries or frameworks that need to maintain compatibility across different Java versions.

Why Multi-Release JAR Files?

As Java continues to evolve, new features are added with each major release. However, third-party libraries often face challenges when updating their code to support these new features. The multi-release JAR feature addresses the problem of maintaining multiple source codes for the same file by allowing platform-specific versions within a single JAR file.

Typical JAR Structure

In a typical JAR file, all classes reside at the root level:

Structure

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

However, if you have a Java 9-specific Util class, that JAR file would not be usable in JRE 8 or lower. This is where the multi-release JAR comes in handy.

Multi-Release JAR Structure

In multi-release JAR files, a MANIFEST.MF file contains the entry Multi-Release: true, and the META-INF/versions directory holds Java version-specific classes:

Structure

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

If the JRE doesn’t support multi-release JAR files, it will load the root-level classes. Otherwise, it will load the version-specific classes. For instance, in Java 8, the root-level Util.class is loaded, but in Java 9, the Java 9-specific Util.class is loaded.

Creating and Using Multi-Release JAR Files

Follow these steps to create and use a multi-release JAR file with Java 7 and Java 9-specific classes.

Step 1: Create Java 7 Specific Class

Create a folder c:/test/java7/com/tutorialsarena and create a file named Tester.java with the following content:

Tester.java (Java 7)

package com.tutorialsarena;

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

Step 2: Create Java 9 Specific Class

Create a folder c:/test/java9/com/tutorialsarena and create a file named Tester.java with the following content:

Tester.java (Java 9)

package com.tutorialsarena;

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

Step 3: Compile with Target Versions

Compile the Java 7 and Java 9 specific classes:

Compilation

C:\test > javac --release 7 java7/com/tutorialsarena/Tester.java
C:\test > javac --release 9 java9/com/tutorialsarena/Tester.java

Step 4: Create the Multi-Release JAR

Create the multi-release JAR using the following command:

Create JAR

C:\test > jar -c -f test.jar -C java7 . --release 9 -C java9 .

Step 5: Run the JAR with JDK 7

Run the JAR on JDK 7 to execute the Java 7-specific class:

Run JAR (JDK 7)

C:\test > java -cp test.jar com.tutorialsarena.Tester
Output

Inside Java 7

Step 6: Run the JAR with JDK 9

Run the JAR on JDK 9 to execute the Java 9-specific class:

Run JAR (JDK 9)

C:\test > java -cp test.jar com.tutorialsarena.Tester
Output

Inside Java 9

Conclusion

With the multi-release JAR feature, you can maintain different versions of classes within a single JAR file, without worrying about backward compatibility. This approach simplifies the codebase and allows frameworks to use new Java features without rewriting older code. The key requirement is that the public interface and method signatures remain the same across different versions of the class.