Zoeken…


Invoering

Een van de functies die is geïntroduceerd in Java 9 is de multi-release Jar (MRJAR) waarmee code kan worden gebundeld die is gericht op meerdere Java-releases binnen hetzelfde Jar-bestand. De functie is gespecificeerd in JEP 238 .

Voorbeeld van de inhoud van een Jar-bestand met meerdere releases

Door Multi-Release: true in het MANIFEST.MF-bestand in te stellen, wordt het Jar-bestand een multi-release Jar en kiest de Java-runtime (zolang het de MRJAR-indeling ondersteunt) de juiste klassenversies, afhankelijk van de huidige hoofdversie .

De structuur van zo'n pot is als volgt:

jar root
  - A.class
  - B.class
  - C.class
  - D.class
  - META-INF
     - versions
        - 9
           - A.class
           - B.class
        - 10
           - A.class
  • Op JDK's <9 zijn alleen de klassen in het root-item zichtbaar voor de Java-runtime.
  • Op een JDK 9 worden de klassen A en B geladen vanuit de map root/META-INF/versions/9 , terwijl C en D worden geladen vanuit het basisitem.
  • Op een JDK 10 zou klasse A worden geladen vanuit de directory root/META-INF/versions/10 .

Een multi-release jar maken met behulp van de jar-tool

Het jar commando kan worden gebruikt om een multi-release jar te maken met twee versies van dezelfde klasse die zijn gecompileerd voor zowel Java 8 als Java 9, zij het met een waarschuwing dat de klassen identiek zijn:

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

De --release 9 optie vertelt jar om alles wat volgt (de include demo -pakket in de sampleproject-9 directory) in een versioned vermelding in de MRJAR, namelijk onder root/META-INF/versions/9 . Het resultaat is de volgende inhoud:

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

Laten we nu een klasse maken met de naam Main die de URL van de SampleClass en deze toevoegen voor de Java 9-versie:

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

Als we deze klasse compileren en het jar-commando opnieuw uitvoeren, krijgen we een foutmelding:

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

De reden is dat de jar tool voorkomt dat openbare klassen worden toegevoegd aan ingevoerde versies als deze niet ook aan de basisitems worden toegevoegd. Dit wordt gedaan zodat de MRJAR dezelfde openbare API voor de verschillende Java-versies blootstelt. Merk op dat deze regel tijdens runtime niet vereist is. Het kan alleen worden toegepast door hulpmiddelen zoals jar . In dit specifieke geval is het doel van Main om voorbeeldcode uit te voeren, dus we kunnen eenvoudig een kopie toevoegen aan het basisitem. Als de klasse deel uitmaakte van een nieuwere implementatie die we alleen voor Java 9 nodig hebben, zou deze klasse niet-openbaar kunnen worden gemaakt.

Om Main aan het root-item toe te voegen, moeten we het eerst compileren om een pre-Java 9-release te targeten. Dit kan met de nieuwe --release optie van 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

Het uitvoeren van de klasse Main laat zien dat de SampleClass wordt geladen vanuit de versiemap:

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 van een geladen klasse in een multi-release jar

Gegeven de volgende multi-release Jar:

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

De volgende klasse drukt de URL van 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);
    }
}

Als de klasse wordt gecompileerd en toegevoegd aan het versie-item voor Java 9 in de MRJAR, zou het uitvoeren:

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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow