Recherche…


Introduction

L'une des fonctionnalités introduites dans Java 9 est le Jar multi-version (MRJAR) qui permet de regrouper du code ciblant plusieurs versions de Java dans le même fichier Jar. La fonctionnalité est spécifiée dans JEP 238 .

Exemple de contenu de fichier Jar multi-version

En définissant Multi-Release: true dans le fichier MANIFEST.MF, le fichier Jar devient un Jar multi-versions et le runtime Java (à condition qu'il prenne en charge le format MRJAR) sélectionne les versions appropriées des classes en fonction de la version majeure actuelle. .

La structure d'un tel pot est la suivante:

jar root
  - A.class
  - B.class
  - C.class
  - D.class
  - META-INF
     - versions
        - 9
           - A.class
           - B.class
        - 10
           - A.class
  • Sur les JDK <9, seules les classes de l'entrée racine sont visibles pour le runtime Java.
  • Sur un JDK 9, les classes A et B seront chargées à partir du répertoire root/META-INF/versions/9 , tandis que C et D seront chargées à partir de l’entrée de base.
  • Sur un JDK 10, la classe A serait chargée à partir du répertoire root/META-INF/versions/10 .

Créer un Jar multi-release à l'aide de l'outil JAR

La commande jar peut être utilisée pour créer un Jar multi-versions contenant deux versions de la même classe compilées pour Java 8 et Java 9, mais avec un avertissement indiquant que les classes sont identiques:

C:\Users\manouti>jar --create --file MR.jar -C sampleproject-base demo --release 9 -C sampleproject-9 demo
Warning: entry META-INF/versions/9/demo/SampleClass.class contains a class that
is identical to an entry already in the jar

L'option --release 9 indique à jar d'inclure tout ce qui suit (le package demo dans le sampleproject-9 ) dans une entrée versionnée du MRJAR, à savoir sous root/META-INF/versions/9 . Le résultat est le contenu suivant:

jar root
  - demo
     - SampleClass.class
  - META-INF
     - versions
        - 9
           - demo
              - SampleClass.class

Créons maintenant une classe appelée Main qui SampleClass l'URL de SampleClass et l'ajoute à la version Java 9:

package demo;

import java.net.URL;

public class Main {

    public static void main(String[] args) throws Exception {
        URL url = Main.class.getClassLoader().getResource("demo/SampleClass.class");
        System.out.println(url);
    }
}

Si nous compilons cette classe et réexécutons la commande jar, nous obtenons une erreur:

C:\Users\manouti>jar --create --file MR.jar -C sampleproject-base demo --release 9 -C sampleproject-9 demoentry: META-INF/versions/9/demo/Main.class, contains a new public class not found in base entries
Warning: entry META-INF/versions/9/demo/Main.java, multiple resources with same name
Warning: entry META-INF/versions/9/demo/SampleClass.class contains a class that
is identical to an entry already in the jar
invalid multi-release jar file MR.jar deleted

La raison en est que l'outil jar empêche l'ajout de classes publiques aux entrées versionnées si elles ne sont pas également ajoutées aux entrées de base. Ceci est fait pour que MRJAR expose la même API publique pour les différentes versions de Java. Notez qu'au moment de l'exécution, cette règle n'est pas requise. Il ne peut être appliqué que par des outils tels que le jar . Dans ce cas particulier, le but de Main est d'exécuter un exemple de code, nous pouvons donc simplement ajouter une copie dans l'entrée de base. Si la classe faisait partie d'une nouvelle implémentation dont nous avons seulement besoin pour Java 9, elle pourrait être rendue non publique.

Pour ajouter Main à l'entrée root, nous devons d'abord le compiler pour cibler une version antérieure à Java 9. Cela peut être fait en utilisant la nouvelle option --release de javac :

C:\Users\manouti\sampleproject-base\demo>javac --release 8 Main.java
C:\Users\manouti\sampleproject-base\demo>cd ../..
C:\Users\manouti>jar --create --file MR.jar -C sampleproject-base demo --release 9 -C sampleproject-9 demo

L'exécution de la classe Main montre que SampleClass est chargé depuis le répertoire versionné:

C:\Users\manouti>java --class-path MR.jar demo.Main
jar:file:/C:/Users/manouti/MR.jar!/META-INF/versions/9/demo/SampleClass.class

URL d'une classe chargée dans un Jar multi-release

Compte tenu du Jar multi-versions suivant:

jar root
  - demo
     - SampleClass.class
  - META-INF
     - versions
        - 9
           - demo
              - SampleClass.class

La classe suivante imprime l'URL de SampleClass :

package demo;

import java.net.URL;

public class Main {

    public static void main(String[] args) throws Exception {
        URL url = Main.class.getClassLoader().getResource("demo/SampleClass.class");
        System.out.println(url);
    }
}

Si la classe est compilée et ajoutée à l'entrée versionnée pour Java 9 dans MRJAR, son exécution entraînerait:

C:\Users\manouti>java --class-path MR.jar demo.Main
jar:file:/C:/Users/manouti/MR.jar!/META-INF/versions/9/demo/SampleClass.class


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow