Programmering

Hvad er JPMS? Introduktion til Java Platform Module System

Indtil Java 9 havde Java's top-niveau kodeorganisationselement været pakken. Startende med Java 9, der ændrede sig: over pakken er nu modulet. Modulet samler relaterede pakker sammen.

Java Platform Module System (JPMS) er en kodestruktur, så det ændrer ikke det faktum, at vi pakker Java i JAR-filer. I sidste ende er alt stadig samlet i JAR-filer. Modulsystemet tilføjer en ny deskriptor på højere niveau, som JAR'er kan bruge, ved at inkorporere modul-info.java fil.

Store apps og organisationer drager fordel af moduler for bedre at organisere kode. Men alle vil forbruge moduler, da JDK og dens klasser nu er moduleret.

Hvorfor Java har brug for moduler

JPMS er resultatet af projektet Jigsaw, som blev gennemført med følgende erklærede mål:

  • Gør det lettere for udviklere at organisere store apps og biblioteker
  • Forbedre strukturen og sikkerheden på platformen og JDK selv
  • Forbedre appens ydeevne
  • Bedre håndteringsnedbrydning af platformen til mindre enheder

Det er værd at bemærke, at JPMS er en SE (Standard Edition) -funktion og derfor påvirker alle aspekter af Java fra bunden. Når det er sagt, er ændringen designet til at tillade det mest kode til at fungere uden ændring, når du flytter fra Java 8 til Java 9. Der er nogle undtagelser fra dette, og vi vil bemærke dem senere i denne oversigt.

Hovedideen bag et modul er at tillade indsamling af relaterede pakker, der er synlige for modulet, samtidig med at elementer gemmes fra eksterne forbrugere af modulet. Med andre ord giver et modul mulighed for et andet niveau af indkapsling.

Klassesti vs. modulsti

I Java har hidtil klassestien været bundlinjen for, hvad der er tilgængeligt for en kørende applikation. Selvom klassestien tjener dette formål og er godt forstået, ender det med at blive en stor, udifferentieret spand, hvor alle afhængigheder er placeret.

Modulstien tilføjer et niveau over klassestien. Det fungerer som en container til pakker og bestemmer, hvilke pakker der er tilgængelige for applikationen.

Moduler i JDK

JDK selv består nu af moduler. Lad os starte med at se på møtrikker og bolte på JPMS der.

Hvis du har en JDK på dit system, har du også kilden. Hvis du ikke er bekendt med JDK, og hvordan du får det, skal du kigge på denne artikel.

Inde i din JDK-installationsmappe er en / lib vejviser. Inde i denne mappe er en src.zip fil. Pak det ud i en / src vejviser.

Se inde i / src bibliotek, og naviger til /java.base vejviser. Der finder du modul-info.java fil. Åbn den.

Efter Javadoc-kommentarerne i spidsen finder du en sektion med navnetmodul java.base efterfulgt af en række eksport linjer. Vi vil ikke dvæle ved formatet her, da det bliver ret esoterisk. Detaljerne kan findes her.

Du kan se, at mange af de velkendte pakker fra Java, ligesom java.io, eksporteres fra java.base modul. Dette er essensen af ​​et modul, der samler pakkerne.

Bagsiden afeksport er kræver instruktion. Dette gør det muligt at kræve et modul af det modul, der defineres.

Når du kører Java-kompilatoren mod moduler, angiver du modulstien på samme måde som klassestien. Dette gør det muligt at løse afhændelser.

Oprettelse af et modulært Java-projekt

Lad os se på, hvordan et moduleret Java-projekt er struktureret.

Vi laver et lille program, der har to moduler, det ene, der leverer en afhængighed, og det andet, der bruger den afhængighed og eksporterer en eksekverbar hovedklasse.

Opret en ny mappe et eller andet sted bekvemt på dit filsystem. Kald det /com.javaworld.mod1. Som konvention lever Java-moduler i et bibliotek, der har samme navn som modulet.

Opret nu en i denne mappe modul-info.java fil. Indvendigt skal du tilføje indholdet fra liste 1.

Liste 1: com.javaworld.mod1 / module-info.java

modul com.javaworld.mod1 {eksporterer com.javaworld.package1; }

Bemærk, at modulet og pakken, det eksporterer, er forskellige navne. Vi definerer et modul, der eksporterer en pakke.

Opret nu en fil på denne sti inde i den mappe, der indeholder modul-info.java fil: /com.javaworld.mod1/com/javaworld/package1. Navngiv filenNavn.java. Læg indholdet af liste 2 inde i det.

Liste 2: Name.java

 pakke com.javaworld.package1; public class Name {public String getIt () {return "Java World"; }} 

Listing 2 bliver en klasse, pakke og modul, som vi er afhængige af.

Lad os nu oprette en anden mappe parallelt med /com.javaworld.mod1 og kald det /com.javaworld.mod2. I denne mappe skal vi oprette en modul-info.java moduldefinition, der importerer det modul, vi allerede har oprettet, som i liste 3.

Liste 3: com.javaworld.mod2 / module-info.java

 modul com.javaworld.mod2 {kræver com.javaworld.mod1; } 

Liste 3 er ret selvforklarende. Det definerer com.javaworld.mod2 modul og kræver com.javaworld.mod1.

Inde i /com.javaworld.mod2 katalog, opret en klassesti som sådan: /com.javaworld.mod2/com/javaworld/package2.

Tilføj nu en fil, der hedder Hej.java, med koden i Listing 4.

Listing 4: Hello.java

 pakke com.javaworld.package2; import com.javaworld.package1.Name; offentlig klasse Hej {public static void main (String [] args) {Name name = new Name (); System.out.println ("Hej" + navn.getIt ()); }} 

I liste 4 begynder vi med at definere pakken og derefter importere com.javawolrd.package1.Name klasse. Vær opmærksom på, at disse elementer fungerer, som de altid har gjort. Modulerne har ændret, hvordan pakkerne gøres tilgængelige på filstrukturniveau, ikke kodeniveau.

På samme måde skal selve koden være kendt for dig. Det opretter simpelthen en klasse og kalder en metode på den for at skabe et klassisk "hej verden" -eksempel.

Kører det modulære Java-eksempel

Det første trin er at oprette mapper til at modtage output fra compileren. Opret en kaldet mappe /mål ved roden af ​​projektet. Indvendigt skal du oprette en mappe til hvert modul: /target/com.javaworld.mod1 og /target/com.javaworld.mod2.

Trin 2 er at kompilere afhængighedsmodulet og udsende det til /mål vejviser. Indtast kommandoen i liste 5 ved projektets rod. (Dette forudsætter, at JDK er installeret.)

Listing 5: Bygningsmodul 1

 javac -d target / com.javaworld.mod1 com.javaworld.mod1 / module-info.java com.javaworld.mod1 / com / javaworld / package1 / Name.java 

Dette får kilden til at blive bygget sammen med dens moduloplysninger.

Trin 3 er at generere det afhængige modul. Indtast kommandoen vist i Listing 6.

Liste 6: Bygningsmodul 2

 javac --module-path target -d target / com.javaworld.mod2 com.javaworld.mod2 / module-info.java com.javaworld.mod2 / com / javaworld / package2 / Hello.java 

Lad os se nærmere på Listing 6. Det introducerer modul-sti argument til javac. Dette giver os mulighed for at definere modulstien på samme måde som --class-path switch. I dette eksempel passerer vi i mål bibliotek, fordi det er her Listing 5 udsender modul 1.

Dernæst definerer Listing 6 (via -d switch) outputkataloget til modul 2. Endelig gives de faktiske kompilationsemner som modul-info.java fil og klasse indeholdt i modul 2.

For at køre skal du bruge kommandoen vist i Listing 7.

Liste 7: Udførelse af modulets hovedklasse

 java -modul-sti-mål -m com.javaworld.mod2 / com.javaworld.package2 Hej 

Det - modul-sti switch fortæller Java at bruge /mål katalog som modulrod, dvs. hvor man skal søge efter modulerne. Det -m switch er, hvor vi fortæller Java, hvad vores hovedklasse er. Bemærk, at vi forordner det fuldt kvalificerede klassenavn med dets modul.

Du vil blive mødt med output Hej Java World.

Bagudkompatibilitet

Du kan meget vel undre dig over, hvordan du kan køre Java-programmer skrevet i præ-modulversioner i posten Java 9-verdenen, da den tidligere kodebase ikke kender noget til modulstien. Svaret er, at Java 9 er designet til at være bagudkompatibel. Det nye modulsystem er dog en så stor ændring, at du kan støde på problemer, især i store kodebaser.

Når du kører en pre-9 codebase mod Java 9, kan du støde på to slags fejl: dem, der stammer fra din codebase, og dem, der stammer fra dine afhængigheder.

For fejl, der stammer fra din codebase, kan følgende kommando være nyttig: jdeps. Denne kommando, når den peges på en klasse eller et bibliotek, scanner efter hvilke afhængigheder der er, og hvilke moduler disse afhængigheder er afhængige af.

For fejl, der stammer fra dine afhængigheder, kan du håbe, at den pakke, du er afhængig af, har en opdateret Java 9-kompatibel build. Hvis ikke skal du muligvis søge efter alternativer.

En almindelig fejl er denne:

Sådan løses java.lang.NoClassDefFoundError: javax / xml / bind / JAXBException

Dette er Java, der klager over, at en klasse ikke findes, fordi den er migreret til et modul uden synlighed til den forbrugende kode. Der er et par løsninger af varierende kompleksitet og varighed, beskrevet her.

Igen, hvis du opdager sådanne fejl med afhængighed, skal du undersøge projektet. De har muligvis en Java 9-build, som du kan bruge.

JPMS er en temmelig gennemgribende ændring, og det vil tage tid at vedtage. Heldigvis er der ikke noget hastehastighed, da Java 8 er en langsigtet supportudgivelse.

Når det er sagt, skal ældre projekter på lang sigt migrere, og nye skal bruge moduler intelligent og forhåbentlig udnytte nogle af de lovede fordele.

Denne historie, "Hvad er JPMS? Introduktion til Java Platform Module System" blev oprindeligt udgivet af JavaWorld.