© DrHitch/Shutterstock.com
Java 9

1 Anwendungen kompilieren, paketieren und ausführen


Nach langer Erwartung wird Java 9 voraussichtlich im September 2017 veröffentlicht. Die neuste Version bietet einige Verbesserungen. Insgesamt 89 Java Enhancement Proposals (JEPs) wurden in Java 9 implementiert. In diesem Kapitel stelle ich das Modulsystem des Projekts Jigsaw vor.

Die größte Änderung in Java 9 ist das neue Modulsystem Projekt Jigsaw. Mithilfe von Projekt Jigsaw wird die Programmierung auf Basis von Softwaremodulen in Java 9 möglich. Dieses Kapitel erläutert Ihnen einen Teil der wichtigsten Grundlagen des Projekts Jigsaw, deren Aufgabe es ist, das Design eines Standardmodulsystems für das JDK 9 und für die Java-Plattform bereitzustellen. Projekt Jigsaw besteht aus insgesamt sechs JEPs und einem JSR:

  • JEP 200: Modulares JDK
  • JEP 201: Modularer Quellcode
  • JEP 220: Modulare Laufzeit-Images
  • JEP 260: Einkapselung von internen APIs
  • JEP 261: Modulares System
  • JEP 282: JLink
  • JSR 376: Java-Plattform-Modulsystem

Die OpenJDK-Webseite stellt unter [1] die Ziele von Projekt Jigsaw eindeutig und präzise vor. So sollen die Java-SE-Plattform und das JDK skalierbarer für kleine Geräte sein. Außerdem sollen die Sicherheit und Wartbarkeit der Java-SE-Plattform sowie die Leistung von Applikationen verbessert werden. Zudem steht die einfachere Entwicklung und Wartbarkeit von Bibliotheken und großen Anwendungen auf dem Plan, sowohl für die Java-SE- als auch für die Java-EE-Plattform.

Java-9-Anwendungen bestehen aus Modulen. Bei der Kompilierung und Ausführung unterstützt Java 9 die Angabe von Modulen. Der Java-Compiler und der Java Launcher wurden mit neuen Flags bereichert, um die Kompilierung und die Ausführung von Java-9-Modulen zu ermöglichen. Zu den wichtigsten neuen Optionen zählen die folgenden Flags: --module-source-path, das dem Java-Compiler den Suchpfad für Module mitteilt, --module-path, das dem Java Launcher die Stelle der kompilierten Module mitteilt sowie --module, das das Hauptmodul nennt.

Außerdem wird das neue Konzept modularer JAR-Dateien vorgestellt. Nebenbei wird erklärt, wie man eine modulare JAR-Datei aus .class-Dateien erzeugen und wie sie für die Ausführung der Module verwendet werden kann. Die meisten internen JDK-APIs sind in JDK 9 nicht mehr zugänglich. Quellcode, der solche internen JDK-APIs verwendet, kann im JDK 9 nicht mehr kompiliert werden. Um die Kapselung auszuschalten, wurde eine neue Java-Compiler-Option namens --add-exports eingeführt. Mithilfe dieser Option kann man spezifizieren, ob ein internes JDK-Paket für ein bestimmtes Modul zugänglich sein soll. Ein konkretes Beispiel mit Quellcode wollen wir uns in diesem Kapitel ansehen.

Das Konzept des Moduls in Java 9

Ein Modul in Jigsaw ist ein Container mit Paketen. Es enthält Ressourcendateien, nativen Quellcode und einen Moduldeskriptor mit dem Namen module-info.java. Die typische Struktur eines Moduls namens com.javamagazin.meinModul sieht folgendermaßen aus:

src/
com.javamagazin.meinModul/
module-info.java
com/javamagazin/meinModul/
// meine Java-Dateien

Das kann der Moduldeskriptor

Der Moduldeskriptor entspricht der Datei module-info.java. Um ein Modul zu definieren, muss die Datei module-info.java auf oberster Paketebene innerhalb eines Moduls vorhanden sein. Die Datei enthält das Schlagwort module, gefolgt von dem Modulnamen und der Moduldeklaration in geschweiften Klammern. Die Deklaration eines Moduls ist einfach. In unserem Beispiel wird ein Modul namens com.javamagazin.meinModul in der Datei module-info.java deklariert:

module com.javamagazin.meinModul {
}

In diesem Fall hat das Modul com.javamagazin.meinModul keine Anweisungen. Das heißt, andere Module können nicht darauf zugreifen und es kann auch auf andere Module nicht zugreifen. Das Prinzip der starken Abkapselung wird in Java 9 standardmäßig erzielt. In unserem Fall haben wir standardmäßig eine starke Abkapselung auf Basis des Geheimnisprinzips, weil wir keine Anweisungen innerhalb des Moduls definieren.

Die Datei module-info.java kann nur die Moduldefinition enthalten, eine Java-Klasse kann in der Datei nicht platziert werden. Außerdem werden zwei oder mehrere Moduldeklarationen in einer einzigen module-info-Datei zu einem Kompilierungsfehler führen. Der Moduldeskriptor module-info.java wird zusammen mit dem Quellcode kompiliert. Als Ergebnis werden .class-Dateien generiert, einschließlich des Moduldeskriptors module-info. Alle kompilierten Dateien können dann als modulare JAR-Dateien verpackt werden. Es gibt jedoch mindestens zwei Fälle, in denen wir nicht eine module-info.java-Datei selbst schreiben müssen: Zum einen ist das der Fall, wenn wir eine JAR-Datei auf den Modulpfad setzen. Dann wird eine module-info.java-Datei automatisch generiert, weil wir ein automatisches Modul damit erzeugen. Zum anderen, wenn wir eine module-info.java-Datei für eine bestimmte JAR-Datei mithilfe des jdeps-Werkzeugs automatisch generieren.

Fünf Anweisungen im Moduldeskriptor

Innerhalb eines Moduldeskriptors können fünf unterschiedliche Anweisungen definiert werden: requires, exports, provides, uses und opens. Die Anweisungen fasst Tabelle 1.1 zusammen.

Anweisung

Beschreibung

requires <Name des Moduls>

Drückt aus, von welchen anderen Modulen das aktuelle Modul abhängt

exports <Name des Pakets>

(to <Name des Moduls>)

Drückt aus, welche Pakete aus dem aktuellen Modul außerhalb des Moduls exportiert werden

uses <Art des Dienstes>

Definiert, dass das aktuelle Modul Instanzen von <Art des Diensts> verbraucht

provides <Name des Diensts> with <Name der Implementierung des Diensts>

Definiert, dass das aktuelle Modul die Implementierung von <Name des Diensts> mit <Name der Implementierung des Diensts> bietet

opens <Name des Pakets>

Stellt das Paket mit dem Namen <Name des Pakets> zur Deep Reflection zur Laufzeit zur Verfügung

Tabelle 1.1: Anweisungen an den Moduldeskriptor

Abhängigkeiten mit der „requires“-Anweisung erfüllen

Die requires-Anweisung wird innerhalb der Moduldeklaration verwendet, um das Modul zu definieren, das wiederum das aktuelle Modul benötigt, um seine Abhängigkeiten zu erfüllen. Die Syntax ist requires <Name von Modul>;. Für jedes Modul müssen wir eine separate requires-Anweisung definieren. Wir zeigen ein Beispiel, bei dem das Modul com.javamagazin.modul...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang