Προγραμματισμός

Τι είναι το JPMS; Παρουσιάζουμε το Java Platform Module System

Μέχρι την Java 9, το στοιχείο οργάνωσης κώδικα ανώτατου επιπέδου της Java ήταν το πακέτο. Ξεκινώντας με το Java 9 που άλλαξε: πάνω από το πακέτο τώρα είναι η ενότητα. Η ενότητα συλλέγει σχετικά πακέτα.

Το Java Platform Module System (JPMS) είναι μια δομή σε επίπεδο κώδικα, επομένως δεν αλλάζει το γεγονός ότι συσκευάζουμε την Java σε αρχεία JAR. Τελικά, όλα συγκεντρώνονται ακόμα σε αρχεία JAR. Το σύστημα λειτουργικών μονάδων προσθέτει έναν νέο, υψηλού επιπέδου περιγραφέα που μπορούν να χρησιμοποιήσουν τα JAR, ενσωματώνοντας το module-info.java αρχείο.

Οι εφαρμογές και οι οργανισμοί μεγάλης κλίμακας θα εκμεταλλευτούν τις ενότητες για την καλύτερη οργάνωση του κώδικα. Όμως όλοι θα καταναλώνουν ενότητες, καθώς το JDK και οι τάξεις του έχουν πλέον διαμορφωθεί.

Γιατί η Java χρειάζεται ενότητες

Το JPMS είναι το αποτέλεσμα του έργου Jigsaw, το οποίο πραγματοποιήθηκε με τους ακόλουθους δηλωμένους στόχους:

  • Διευκολύνετε τους προγραμματιστές να οργανώνουν μεγάλες εφαρμογές και βιβλιοθήκες
  • Βελτιώστε τη δομή και την ασφάλεια της πλατφόρμας και του ίδιου του JDK
  • Βελτιώστε την απόδοση της εφαρμογής
  • Καλύτερη αποσύνθεση λαβής της πλατφόρμας για μικρότερες συσκευές

Αξίζει να σημειωθεί ότι το JPMS είναι ένα χαρακτηριστικό SE (Standard Edition) και επομένως επηρεάζει κάθε πτυχή της Java από την αρχή. Τούτου λεχθέντος, η αλλαγή έχει σχεδιαστεί για να επιτρέπει πλέον κώδικα για λειτουργία χωρίς τροποποίηση κατά τη μετάβαση από την Java 8 στην Java 9. Υπάρχουν ορισμένες εξαιρέσεις σε αυτό και θα τις σημειώσουμε αργότερα σε αυτήν την επισκόπηση.

Η κύρια ιδέα πίσω από μια ενότητα είναι να επιτρέψει τη συλλογή σχετικών πακέτων που είναι ορατά στη μονάδα, ενώ κρύβονται στοιχεία από εξωτερικούς καταναλωτές της μονάδας. Με άλλα λόγια, μια ενότητα επιτρέπει ένα άλλο επίπεδο ενθυλάκωσης.

Διαδρομή κατηγορίας έναντι διαδρομής ενότητας

Στην Java μέχρι τώρα η διαδρομή κλάσης ήταν η κατώτατη γραμμή για ό, τι είναι διαθέσιμο σε μια εφαρμογή που εκτελείται. Αν και η διαδρομή της τάξης εξυπηρετεί αυτόν τον σκοπό και είναι καλά κατανοητή, καταλήγει να είναι ένας μεγάλος, αδιαφοροποίητος κάδος στον οποίο τοποθετούνται όλες οι εξαρτήσεις.

Η διαδρομή ενότητας προσθέτει ένα επίπεδο πάνω από τη διαδρομή κλάσης. Χρησιμεύει ως κοντέινερ για πακέτα και καθορίζει ποια πακέτα είναι διαθέσιμα στην εφαρμογή.

Ενότητες στο JDK

Το ίδιο το JDK αποτελείται από ενότητες τώρα. Ας ξεκινήσουμε κοιτάζοντας τα παξιμάδια και τα μπουλόνια του JPMS εκεί.

Εάν έχετε JDK στο σύστημά σας, έχετε επίσης την πηγή. Εάν δεν είστε εξοικειωμένοι με το JDK και πώς να το αποκτήσετε, ρίξτε μια ματιά σε αυτό το άρθρο.

Μέσα στον κατάλογο εγκατάστασης JDK είναι ένας / lib Ευρετήριο. Μέσα σε αυτόν τον κατάλογο είναι ένα src.zip αρχείο. Αποσυμπιέστε σε ένα / src Ευρετήριο.

Κοιτάξτε μέσα στο / src κατάλογο και μεταβείτε στο /java.base Ευρετήριο. Εκεί θα βρείτε το module-info.java αρχείο. Ανοίξτε το.

Μετά τα σχόλια Javadoc στο κεφάλι, θα βρείτε μια ενότητα με το όνομαενότητα java.base ακολουθούμενη από μια σειρά από εξαγωγές γραμμές. Δεν θα σταθούμε στη μορφή εδώ, καθώς γίνεται αρκετά εσωτερική. Μπορείτε να βρείτε τις λεπτομέρειες εδώ.

Μπορείτε να δείτε ότι πολλά από τα γνωστά πακέτα από την Java, όπως java.io, εξάγονται από το java.base μονάδα μέτρησης. Αυτή είναι η ουσία μιας ενότητας που συγκεντρώνει τα πακέτα.

Η άλλη πλευρά τουεξαγωγές είναι το απαιτεί εντολή. Αυτό επιτρέπει να απαιτείται μια ενότητα από τον καθορισμό της ενότητας.

Κατά την εκτέλεση του μεταγλωττιστή Java σε ενότητες, καθορίζετε τη διαδρομή της μονάδας με παρόμοιο τρόπο με τη διαδρομή κλάσης. Αυτό επιτρέπει την επίλυση των εξαρτήσεων.

Δημιουργία ενός αρθρωτού έργου Java

Ας ρίξουμε μια ματιά στον τρόπο δομής ενός διαμορφωμένου έργου Java.

Πρόκειται να φτιάξουμε ένα μικρό πρόγραμμα με δύο ενότητες, μία που παρέχει εξάρτηση και η άλλη που χρησιμοποιεί αυτήν την εξάρτηση και εξάγει μια εκτελέσιμη κύρια κατηγορία.

Δημιουργήστε έναν νέο κατάλογο κάπου βολικό στο σύστημα αρχείων σας. Κάλεσε το /com.javaworld.mod1. Κατά συνθήκη, οι λειτουργικές μονάδες Java ζουν σε έναν κατάλογο που έχει το ίδιο όνομα με τη λειτουργική μονάδα.

Τώρα, μέσα σε αυτόν τον κατάλογο, δημιουργήστε ένα module-info.java αρχείο. Στο εσωτερικό, προσθέστε το περιεχόμενο από την καταχώριση 1.

Λίστα 1: com.javaworld.mod1 / module-info.java

module com.javaworld.mod1 {export com.javaworld.package1; }

Παρατηρήστε ότι η ενότητα και το πακέτο που εξάγει είναι διαφορετικά ονόματα. Ορίζουμε μια ενότητα που εξάγει ένα πακέτο.

Τώρα δημιουργήστε ένα αρχείο σε αυτήν τη διαδρομή, μέσα στον κατάλογο που περιέχει το module-info.java αρχείο: /com.javaworld.mod1/com/javaworld/package1. Ονομάστε το αρχείοΌνομα. Java. Τοποθετήστε το περιεχόμενο της καταχώρισης 2 μέσα σε αυτό.

Λίστα 2: Name.java

 πακέτο com.javaworld.package1; δημόσια τάξη Όνομα {public String getIt () {return "Java World"; }} 

Η λίστα 2 θα γίνει μια τάξη, ένα πακέτο και μια ενότητα από την οποία εξαρτώνται.

Τώρα ας δημιουργήσουμε έναν άλλο κατάλογο παράλληλο με /com.javaworld.mod1 και καλέστε το /com.javaworld.mod2. Σε αυτόν τον κατάλογο, ας δημιουργήσουμε ένα module-info.java ορισμός λειτουργικής μονάδας που εισάγει τη λειτουργική μονάδα που έχουμε ήδη δημιουργήσει, όπως στην Λίστα 3.

Λίστα 3: com.javaworld.mod2 / module-info.java

 module com.javaworld.mod2 {απαιτεί com.javaworld.mod1; } 

Η λίστα 3 είναι αρκετά αυτονόητη. Ορίζει το com.javaworld.mod2 ενότητα και απαιτεί com.javaworld.mod1.

μεσα στην /com.javaworld.mod2 κατάλογος, δημιουργήστε μια διαδρομή κατηγορίας όπως: /com.javaworld.mod2/com/javaworld/package2.

Τώρα προσθέστε ένα αρχείο στο οποίο ονομάζεται Γεια σου. Java, με τον κωδικό που παρέχεται στην καταχώριση 4.

Λίστα 4: Hello.java

 πακέτο com.javaworld.package2; εισαγωγή com.javaworld.package1.Name; δημόσια τάξη Γεια σας {public static void main (String [] args) {Name name = new Name (); System.out.println ("Γεια" + name.getIt ()); }} 

Στην Λίστα 4, ξεκινάμε ορίζοντας το πακέτο και μετά εισάγουμε το com.javawolrd.package1.Ονομα τάξη. Λάβετε υπόψη ότι αυτά τα στοιχεία λειτουργούν όπως πάντα. Οι μονάδες έχουν αλλάξει τον τρόπο με τον οποίο διατίθενται τα πακέτα σε επίπεδο δομής αρχείου και όχι σε επίπεδο κώδικα.

Ομοίως, ο ίδιος ο κώδικας θα πρέπει να είναι γνωστός σε εσάς. Δημιουργεί απλά μια τάξη και καλεί μια μέθοδο για να δημιουργήσει ένα κλασικό παράδειγμα «γειά σου κόσμος».

Εκτέλεση του αρθρωτού παραδείγματος Java

Το πρώτο βήμα είναι να δημιουργήσετε καταλόγους για να λάβετε την έξοδο του μεταγλωττιστή. Δημιουργήστε έναν κατάλογο που ονομάζεται /στόχος στη ρίζα του έργου. Στο εσωτερικό, δημιουργήστε έναν κατάλογο για κάθε ενότητα: /target/com.javaworld.mod1 και /target/com.javaworld.mod2.

Το βήμα 2 είναι η μεταγλώττιση της μονάδας εξάρτησης, εξάγοντας την στο /στόχος Ευρετήριο. Στη ρίζα του έργου, εισαγάγετε την εντολή στη λίστα 5. (Αυτό προϋποθέτει ότι το JDK είναι εγκατεστημένο.)

Λίστα 5: Ενότητα δόμησης 1

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

Αυτό θα προκαλέσει την κατασκευή της πηγής μαζί με τις πληροφορίες της μονάδας.

Το βήμα 3 είναι η δημιουργία της εξαρτώμενης μονάδας. Εισαγάγετε την εντολή που εμφανίζεται στην καταχώριση 6.

Λίστα 6: Ενότητα δόμησης 2

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

Ας ρίξουμε μια ματιά στην Καταχώριση 6 λεπτομερώς. Εισάγει το ενότητα-διαδρομή επιχείρημα για javac. Αυτό μας επιτρέπει να ορίσουμε τη διαδρομή της μονάδας με παρόμοιο τρόπο με τον διακόπτη --class-path. Σε αυτό το παράδειγμα, περνάμε στο στόχος κατάλογο, επειδή εκεί είναι που η Λίστα 5 εξάγει την Ενότητα 1.

Στη συνέχεια, η Λίστα 6 ορίζει (μέσω του -ρε διακόπτης) τον κατάλογο εξόδου για την Ενότητα 2. Τέλος, δίνονται τα πραγματικά θέματα της συλλογής, όπως το module-info.java αρχείο και τάξη που περιέχονται στην Ενότητα 2.

Για εκτέλεση, χρησιμοποιήστε την εντολή που εμφανίζεται στην καταχώριση 7.

Λίστα 7: Εκτέλεση της κύριας τάξης της ενότητας

 java --module-path target -m com.javaworld.mod2 / com.javaworld.package2. Γεια σας 

ο - διαδρομή ενότητας ο διακόπτης λέει στην Java να χρησιμοποιήσει /στόχος κατάλογος ως ρίζα λειτουργικής μονάδας, δηλαδή πού να αναζητήσετε τις ενότητες. ο ο διακόπτης είναι όπου λέμε στην Java ποια είναι η κύρια τάξη μας. Παρατηρήστε ότι προλογίζουμε το πλήρως αναγνωρισμένο όνομα τάξης με τη λειτουργική του μονάδα.

Θα σας υποδεχτεί με την έξοδο Γεια σας Java World.

Συμβατότητα προς τα πίσω

Ίσως αναρωτιέστε πώς μπορείτε να εκτελέσετε προγράμματα Java γραμμένα σε εκδόσεις προ-ενότητας στον κόσμο μετά το Java 9, δεδομένου ότι η προηγούμενη βάση κώδικα δεν γνωρίζει τίποτα για τη διαδρομή της λειτουργικής μονάδας. Η απάντηση είναι ότι το Java 9 έχει σχεδιαστεί για να είναι συμβατό με το πίσω μέρος. Ωστόσο, το νέο σύστημα λειτουργικών μονάδων είναι μια τόσο μεγάλη αλλαγή που μπορεί να αντιμετωπίσετε προβλήματα, ειδικά σε μεγάλες βάσεις κώδικα.

Κατά την εκτέλεση μιας προ-9 βάσης κώδικα έναντι της Java 9, ενδέχεται να αντιμετωπίσετε δύο είδη σφαλμάτων: αυτά που προέρχονται από τη βάση κώδικα και αυτά που προέρχονται από τις εξαρτήσεις σας.

Για σφάλματα που προέρχονται από τη βάση κώδικα, η ακόλουθη εντολή μπορεί να είναι χρήσιμη: jdeps. Αυτή η εντολή όταν επισημαίνεται σε μια τάξη ή κατάλογο θα σαρώσει για τις εξαρτήσεις που υπάρχουν και σε ποιες ενότητες βασίζονται αυτές οι εξαρτήσεις.

Για σφάλματα που προέρχονται από τις εξαρτήσεις σας, μπορείτε να ελπίζετε ότι το πακέτο στο οποίο βασίζεστε θα έχει μια ενημερωμένη έκδοση συμβατή με Java 9. Εάν όχι, ίσως χρειαστεί να αναζητήσετε εναλλακτικές λύσεις.

Ένα κοινό σφάλμα είναι αυτό:

Τρόπος επίλυσης java.lang.NoClassDefFoundError: javax / xml / bind / JAXBException

Αυτή η Java παραπονιέται ότι δεν βρέθηκε κλάση, επειδή έχει μεταναστεύσει σε μια λειτουργική μονάδα χωρίς ορατότητα στον κώδικα που καταναλώνει. Υπάρχουν μερικές λύσεις διαφορετικής πολυπλοκότητας και μονιμότητας, που περιγράφονται εδώ.

Και πάλι, εάν ανακαλύψετε τέτοια σφάλματα με εξάρτηση, επικοινωνήστε με το έργο. Μπορεί να έχουν μια έκδοση Java 9 για να χρησιμοποιήσετε.

Το JPMS είναι μια αρκετά σαρωτική αλλαγή και θα χρειαστεί χρόνος για να υιοθετηθεί. Ευτυχώς, δεν υπάρχει επείγουσα βιασύνη, καθώς το Java 8 είναι μια μακροπρόθεσμη έκδοση υποστήριξης.

Τούτου λεχθέντος, μακροπρόθεσμα, τα παλαιότερα έργα θα πρέπει να μετεγκατασταθούν και τα νέα θα πρέπει να χρησιμοποιούν έξυπνα modules, ελπίζοντας ότι θα αξιοποιήσουν μερικά από τα υποσχεθέντα οφέλη.

Αυτή η ιστορία, "Τι είναι το JPMS; Παρουσιάζοντας το Java Platform Module System" δημοσιεύθηκε αρχικά από το JavaWorld.