Java 9 introduceerde het idee van modulaire runtime-afbeeldingen met Project Jigsaw en loste officieel het probleem op van het verzenden van Java-runtime als monolithische artefacten. Monolithische runtime-images waren niet alleen zwaar voor het geheugengebruik, maar verminderden ook de algehele prestaties van de applicatie die erop werd uitgevoerd. We kunnen nu een op maat gemaakte subset van JRE inpakken, gebaseerd op de individuele behoeften van de applicaties die erop draaien, en hun efficiëntie vergroten. Dit artikel werpt een holistische kijk op deze functie van aangepaste runtime-images die zijn geïntroduceerd met Java 9.
Een overzicht
De impact van het idee om een modulaire runtime-image te maken met Java 9 is enorm. Het opent de deur voor een op maat gemaakte applicatie vanaf het platform waarop het draait. Het Java-platform heeft bij elke nieuwe versie zijn functionaliteit vergroot. Het is geen verrassing dat de runtime op een gegeven moment een monolithisch artefact zal zijn en een zware tol zal eisen van het geheugen en de prestaties. Hierdoor vragen ontwikkelaars al lang om een uitweg uit dit probleem. Ook gebruiken de meeste programma's Java Platform niet in zijn geheel. Als een programma kan worden geoptimaliseerd voor prestaties en geheugengebruik, waarom kan dan het platform waarop het draait ook niet worden aangepast? Java 8 nam de eerste stap en probeerde een bepaald aspect ervan te implementeren met Compact Profiles . Java 9 ging verder en implementeerde een manier om aangepaste runtime-images te maken zonder beperkingen die Compact Profiles opgelegd. Er was een holistische benadering nodig bij het verpakken van runtime-afbeeldingen. Het platform zelf is modulair opgebouwd om deze functie mogelijk te maken. Applicatiecode verpakt in modules kan worden geleverd met aangepaste runtime-images die alleen die platformmodules bevatten die door de applicatie worden gebruikt. Een applicatieprogramma kan dus een enkel gebundeld artefact zijn dat de aangepaste JRE bevat. Dit maakt zeker gebruik van de prestaties, wat een opstarttijd oplevert met minder geheugenvoetafdrukken. Als de applicatie in de Cloud draait, verminderen deze de overbelasting van het netwerk en de downloadtijd aanzienlijk.
Compact profiel
Hoewel Java 9 voorbij het concept van Compact Profile kwam, geïntroduceerd met Java 8, is het vaak nuttig om de bereikte mijlpaal te begrijpen en te waarderen. In zekere zin voedde Java 9 het idee en verbeterde het concept van een Compact Profile op een meer holistische manier.
Een Compact Profiel definieert subsets van de Java SE-platform-API die de statische grootte van de Java-runtime kunnen verminderen. Dit idee is in feite bedoeld om te werken op apparaten met beperkte middelen en een kleinere opslagcapaciteit, zoals een ingebed apparaat. Er zijn in principe drie profielen, genaamd compact1 , compact2 , en compact3 . Elk hoger genummerd profiel is een superset van het verlaagde genummerde profiel. Dit betekent dat compact1 is een juiste subset van compact2 , compact2 is een juiste subset van compact3 , en compact3 , is op zijn beurt een goede subset van de volledige Java 8 SE API.
Referenties:
- Compacte profielen, Java SE 8-documentatie
- Overzicht van Java SE Embedded 8 compacte profielen
- Een inleiding tot Java 8 compacte profielen
Introductie van JIMAGE
De JIMAGE is een speciaal bestandsformaat dat is geïntroduceerd met Java 9 om aangepaste runtime-afbeeldingen op te slaan. Dit bestandsformaat is geoptimaliseerd voor prestaties en opslag. Het bestandsformaat fungeert in feite als een container voor JDK-bronnen, klassen en modules en indexeert ze voor snel zoeken en sneller laden van klassen. In tegenstelling tot andere bestandsindelingen zoals JAR's en JMOD's, wordt JIMAGE zelden gebruikt door ontwikkelaars omdat het betrekking heeft op JDK-internals, behalve wanneer men een aangepast runtime-image wil bouwen. Het laden van klassen is sneller met JIMAGE dan met JAR's of JMOD's, omdat het daar specifiek voor is geoptimaliseerd. JIMAGE kan ook alleen tijdens runtime worden gebruikt. JIMAGE staat nog in de kinderschoenen. Er is heel weinig informatie over ontwikkelaars beschikbaar; misschien wordt er later meer onthuld.
Aangepaste afbeeldingen maken
Java 9 levert de jlink tool om platformspecifieke runtime-images te maken. Aangepaste afbeeldingen bevatten applicatiespecifieke modules en de vereiste modules van het platform. Omdat de grootte van de runtime-image, ook wel JRE genoemd, tot het absolute minimum is beperkt, is de applicatie-image samen met de JRE ook minimaal. Het bundelt de JRE als een enkele leveringseenheid samen met het programma. De jlink tool bevindt zich in de /bin directory van de JDK9 geïnstalleerde map. Er zijn verschillende opties beschikbaar die aan deze tool zijn gekoppeld en die naar behoefte kunnen worden gebruikt. De beschrijving kan worden verkregen met behulp van de –help optie beschikbaar met de jlink opdracht. Hier wordt het voor het gemak geëxtraheerd, of u kunt jlink –help . typen in de opdrachtregel om de volgende lijst te verkrijgen.
Gebruik:
jlink <options> --module-path <modulepath> --add-modules <module>[,<module>...]
Optie | Beschrijving |
–add-modules | Rootmodules om op te lossen |
–bind-services | Link in serviceprovidermodules en hun afhankelijkheden |
-c, –compress=<0|1|2>
–disable-plugin
–endian | Compressie van bronnen inschakelen: Niveau 0:Geen compressie Niveau 1:constant delen van strings Niveau 2:ZIP Schakel de genoemde plug-in uit Bytevolgorde van gegenereerde jimage (standaard:native) |
-h, –help –ignore-signing-informatie
–launcher
–limit-modules –lijst-plug-ins | Druk dit hulpbericht af Onderdruk een fatale fout wanneer ondertekende modulaire JAR's in de afbeelding zijn gekoppeld. De handtekeninggerelateerde bestanden van de ondertekende modulaire JAR's worden niet gekopieerd naar de runtime-image. Voeg een opstartopdracht toe met de opgegeven naam voor de module en de hoofdklasse, indien gespecificeerd. Beperk het universum van waarneembare modules. Lijst beschikbare plug-ins. |
-p, –module-pad –geen-header-bestanden –geen-man-pagina's
–uitvoer
–save-opts | Modulepad Uitsluiten inclusief header-bestanden Man-pagina's uitsluiten Locatie van uitvoerpad Bewaar jlink-opties in het opgegeven bestand |
-G, –strip-debug
–suggest-providers [ | Foutopsporingsinformatie verwijderen Aanbieders voorstellen die de gegeven servicetypes uit het modulepad implementeren |
-v, –uitgebreide –versie
@ | Uitgebreide tracering inschakelen Versie-informatie Lees opties uit bestand |
Een eenvoudig voorbeeld
Hier zullen we van het begin tot het einde een heel eenvoudig programma doorlopen om een runtime-image van een Java-toepassing te maken. We gaan ervan uit dat JDK9 correct is geïnstalleerd en het PATH en JAVA_HOME omgevingsvariabele op de juiste manier zijn ingesteld. In mijn geval is het als volgt geïnstalleerd en ingesteld (op een Linux-platform):
- JDK9 geïnstalleerde map /usr/lib/jvm/java-9-oracle
- PAD is ingesteld op /usr/lib/jvm/java-9-oracle/bin
- JAVA_HOME is ingesteld op /usr/lib/jvm/java-9-oracle
Stap 1
Maak een map met de naam /Home/SampleProject en een src map erin (bijvoorbeeld /Home/SampleProject/src ).
Stap 2
Maak een map met de naam org.app.test binnen de src directory (bijvoorbeeld /Home/SampleProject/src/org.app.test ).
Stap 3
Nu, binnen de org.app.test directory, maak een bestand aan met de naam module-info.java . En typ de volgende inhoud:
module org.app.test{ requires javafx.controls; exports org.app.test; }
Stap 4
Maak nu een map met de naam org, app, test de een in de ander (bijvoorbeeld org.app.test/org/app/test ) en maak vervolgens een bestand met de naam MyApplication.java binnen de test map en typ de volgende inhoud:
package org.app.test; import javafx.application.Application; import javafx.scene.control.Alert; import javafx.scene.control.ButtonType; import javafx.stage.Stage; public class MyApplication extends Application{ public static void main(String[] args) { Application.launch(args); } @Override public void start(Stage stage) throws Exception { Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setTitle("Congratulation!"); alert.setHeaderText("You did it. The application is running. Press OK to close"); alert.setContentText("You have successfully created a custom image"); alert.showAndWait().ifPresent(rs -> { if (rs == ButtonType.OK) { System.out.println("Pressed OK."); } }); } }
Stap 5
Maak een /Home/SampleProject/mods map. Hier slaan we de gecompileerde code op. Compileer de broncode als volgt. De huidige werkdirectory is /Home/SampleProject .
javac -d mods --module-source-path src src/org.app.test/module-info.java src/org.app.test/org/app/test/MyApplication.java
Stap 6
Laten we nu het JAR-bestand maken en opslaan in de lib directory (zoals /Home/SampleProject/lib ) als volgt:
jar --create --file lib/org.app.test.jar --main-class org.app.test.MyApplication -C mods/org.app.test .
Stap 7
Voer de applicatie als volgt uit om te testen:
java --module-path lib -m org.app.test
Stap 8
Laten we nu het JMOD-bestand maken en opslaan in de jmods directory (bijvoorbeeld Home/SampleProject/jmods ):
jmod create --class-path lib/org.app.test.jar jmods/org.app.test.jmod
Stap 9
Laten we tot slot de aangepaste afbeelding maken met behulp van de volgende opdracht:
jlink --module-path /usr/lib/jvm/java-9-oracle/jmods/:jmods --add-modules org.app.test --launcher runapp=org.app.test --output dist
Hiermee wordt een map gemaakt met de naam dist die alles bevat wat nodig is om de toepassing uit te voeren. Het programma, met de naam van het opstartprogramma gegeven als runapp , is opgenomen in de dist/bin map. Dubbelklik erop om het uit te voeren.
Figuur 1: Het programma loopt
Dat is alles.
Conclusie
Raadpleeg de juiste documentatie voor een gedetailleerde beschrijving van elk van de opdrachtopties die in dit artikel worden gebruikt. Probeer een eenvoudig programma en bouw het van begin tot eind op. Dit zou het nodige vertrouwen opbouwen om te experimenteren met een iets gecompliceerder programma, zoals het gebruik van meer dan één module en het omgaan met hun afhankelijkheden. JDK9 heeft ontwikkelaars in staat gesteld om hun runtime-bagage voor te bereiden om te worden gevuld met alleen noodzakelijke modules. Dit is verbazingwekkend en uitstekend, iets wat de meesten van ons al heel lang van Java verwachten. Een Java-applicatie kan nu de bagage van zich afschudden die het voor ogenschijnlijk weinig reden moest dragen en platformgeoptimaliseerd worden in distributie.