Suche…


Einführung

Eine der in Java 9 eingeführten Funktionen ist die Multi-Release-Jar (MRJAR), die die Bündelung von Code für mehrere Java-Releases in derselben Jar-Datei ermöglicht. Die Funktion ist in JEP 238 angegeben .

Beispiel für den Inhalt einer Jar-Datei mit mehreren Versionen

Durch Festlegen von Multi-Release: true in der MANIFEST.MF-Datei wird die Jar-Datei zu einer Multi-Release-Jar und die Java-Laufzeitumgebung (sofern das MRJAR-Format unterstützt wird) wählt die entsprechenden Klassenversionen abhängig von der aktuellen Hauptversion aus .

Die Struktur eines solchen Bechers ist wie folgt:

jar root
  - A.class
  - B.class
  - C.class
  - D.class
  - META-INF
     - versions
        - 9
           - A.class
           - B.class
        - 10
           - A.class
  • Bei JDKs <9 sind nur die Klassen im Root-Eintrag für die Java-Laufzeitumgebung sichtbar.
  • Auf einem JDK 9 werden die Klassen A und B aus dem Verzeichnis root/META-INF/versions/9 geladen, während C und D aus dem Basiseintrag geladen werden.
  • Auf einem JDK 10 wird Klasse A aus dem Verzeichnis root/META-INF/versions/10 geladen.

Ein Mehrfach-Release-Jar mit dem Jar-Tool erstellen

Mit dem Befehl jar können Sie eine Jar-Version mit mehreren Versionen erstellen, die zwei Versionen derselben Klasse enthält, die sowohl für Java 8 als auch für Java 9 kompiliert wurden. Die Warnung gibt jedoch an, dass die Klassen identisch sind:

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

Die Option --release 9 weist jar an, alles, was folgt (das demo Paket im sampleproject-9 ), in einen versionierten Eintrag in der MRJAR aufzunehmen, und zwar unter root/META-INF/versions/9 . Das Ergebnis ist folgender Inhalt:

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

Lassen Sie uns nun eine Klasse namens Main erstellen, die die URL der SampleClass , und fügen Sie sie für die Java 9-Version hinzu:

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);
    }
}

Wenn wir diese Klasse kompilieren und den JAR-Befehl erneut ausführen, wird ein Fehler angezeigt:

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

Der Grund ist, dass das jar Tool das Hinzufügen öffentlicher Klassen zu versionierten Einträgen verhindert, wenn diese nicht ebenfalls zu den Basiseinträgen hinzugefügt werden. Dies geschieht, damit der MRJAR dieselbe öffentliche API für die verschiedenen Java-Versionen verfügbar macht. Beachten Sie, dass diese Regel zur Laufzeit nicht erforderlich ist. Es kann nur von Werkzeugen wie dem jar angewendet werden. In diesem speziellen Fall besteht der Zweck von Main darin, Beispielcode auszuführen, sodass wir einfach eine Kopie im Basiseintrag hinzufügen können. Wenn die Klasse Teil einer neueren Implementierung war, die wir nur für Java 9 benötigen, könnte sie nicht öffentlich gemacht werden.

Um Main zum Root-Eintrag hinzuzufügen, müssen wir ihn zunächst für ein Pre-Java 9-Release kompilieren. Dies kann mit der neuen Option --release von 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

Das Ausführen der Main-Klasse zeigt, dass die SampleClass aus dem versionierten Verzeichnis geladen wird:

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 einer geladenen Klasse in einer Jar mit mehreren Versionen

Angesichts der folgenden Multi-Release-Jar:

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

Die folgende Klasse druckt die URL der 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);
    }
}

Wenn die Klasse kompiliert und zu dem versionierten Eintrag für Java 9 in der MRJAR hinzugefügt wird, führt das Ausführen zu folgendem Ergebnis:

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
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow