Sök…


Introduktion

En av funktionerna som introducerats i Java 9 är multi-release Jar (MRJAR) som tillåter paketkod som är inriktad på flera Java-releaser i samma Jar-fil. Funktionen anges i JEP 238 .

Exempel på innehållet i en Jar-fil med flera släpp

Genom att ställa in Multi-Release: true i MANIFEST.MF-filen blir Jar-filen en multi-release Jar och Java-runtime (så länge den stöder MRJAR-formatet) kommer att välja lämpliga versioner av klasser beroende på den aktuella större versionen .

Strukturen för en sådan burk är följande:

jar root
  - A.class
  - B.class
  - C.class
  - D.class
  - META-INF
     - versions
        - 9
           - A.class
           - B.class
        - 10
           - A.class
  • På JDK: er <9 är det bara klasserna i rotposten som är synliga för Java-runtime.
  • På en JDK 9 kommer klasserna A och B att laddas från root/META-INF/versions/9 , medan C och D kommer att laddas från basposten.
  • På en JDK 10 laddas klass A från root/META-INF/versions/10 .

Skapa en burk med flera frisättningar med hjälp av burkverktyget

jar kommandot kan användas för att skapa en multi-release jar som innehåller två versioner av samma klass sammanställd för både Java 8 och Java 9, om än med en varning som säger att klasserna är identiska:

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

Den --release 9 alternativet anger jar till att omfatta allt som följer (den demo paket inne i sampleproject-9 katalog) i en versions post i MRJAR, nämligen enligt root/META-INF/versions/9 . Resultatet är följande innehåll:

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

Låt oss nu skapa en klass som heter Main som skriver ut URL: en för SampleClass och lägger till den för Java 9-versionen:

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

Om vi sammanställer denna klass och kör igen jar-kommandot får vi ett fel:

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

Anledningen är att jar förhindrar att offentliga klasser läggs till i versionerade poster om de inte också läggs till i basposterna. Detta görs så att MRJAR exponerar samma offentliga API för de olika Java-versionerna. Observera att vid körning krävs inte denna regel. Det får bara användas av verktyg som jar . I det här fallet är syftet med Main att köra provkod, så att vi helt enkelt kan lägga till en kopia i basposten. Om klassen var en del av en nyare implementering som vi bara behöver för Java 9, skulle den kunna göras icke-offentlig.

För att lägga till Main till rotposten måste vi först kompilera den för att rikta in en pre-Java 9-version. Detta kan göras med hjälp av den nya --release alternativet 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

Att köra huvudklassen visar att SampleClass laddas från den versionerade katalogen:

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 till en laddad klass i en flersläppande burk

Följande flaska med flera släpp:

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

Följande klass skriver ut URL: en för 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);
    }
}

Om klassen kompileras och läggs till i den versionerade posten för Java 9 i MRJAR, skulle den köra resultera i:

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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow