© Excellent backgrounds/Shutterstock.com
Teil 4: Project Jigsaw aka Java Module System

Eine Anwendung in vielen Teilen


Wir wollen Ihnen in dieser Artikelreihe einen Überblick über die Neuerungen in Java 9 verschaffen und einige Features von Java 9 kurz erläutern. Dabei haben wir diejenigen Themen ausgewählt, von denen wir denken, dass sie für Java-Entwickler am interessantesten sind. Und natürlich werfen wir einen Blick auf die größte Neuerung: das Modulsystem.

Mit dem Release 9 bekommt Java nun endlich das schon lange angekündigte Modulsystem [1]. Oracle hat bereits vor etwa fünf Jahren damit begonnen, die Modularisierung von Java-Anwendungen zu unterstützen. In diesem Zuge wurde zunächst einmal das JDK selbst restrukturiert und in Module aufgeteilt. Die Modularisierung des JDK ist nun fertig, und damit hat sich das Deployment des JDK geändert: Es gibt in Java 9 nun kein rt.jar mehr, stattdessen besteht das JDK jetzt aus Modulen. Diesem Beispiel soll die Java-Community folgen. Die Idee ist, dass mit Java 9 eine Transitionsphase beginnt, in der insbesondere Third-Party-Anbieter und schließlich alle Java-Anwendungen ihre Java-Software modularisieren.

Was ist ein Modul?

Module sind Artefakte, die eine Einheit von miteinander zusammenhängenden Klassen, nativem Code und Properties bilden. Zu jedem Modul gehören Metadaten, die das Modul und seine Beziehungen zu anderen Modulen beschreiben. Das Hauptziel der Modularisierung ist die Kapselung von zusammenhängenden Klassen und die saubere Beschreibung der Beziehungen zwischen den Modulen. Ein Modul in Java beschreibt:

  • Readability: welche anderen Module dieses Modul benutzt

  • Accessibility: welche Packages dieses Modul anderen Modulen zur Verfügung stellt

Der Zweck des Modulsystems ist es, diese Beziehungen der Module untereinander von der Übersetzung bis zur Laufzeit zu überprüfen und sicherzustellen.

Wozu braucht Java ein Modulsystem?

Die Möglichkeit, zusammenhängende Klassen zusammenzufassen, gibt es bereits mit den Java-Archiven, d. h. den JAR-Dateien. Außerdem gibt es in Java Kapselungsmechanismen mithilfe von Packages und den Visibility-Deklarationen über private, protected und public. Wozu also braucht es ein Modulsystem für Java? Schauen wir uns einige der Gründe an, die dazu geführt haben, dass ein Modulsystem für Java definiert wurde.

Die Visibility-Deklarationen beispielsweise haben sich als unzureichend herausgestellt. Ein gutes Beispiel für die Defizite sind die JDK-Klassen in den sun.*-Packages wie die Klasse sun.misc.Unsafe. Alle Klassen in den sun.*-Packages waren ursprünglich als interne Klassen für die Implementierung des JDK gedacht und sollten auf keinen Fall allen beliebigen Java-Benutzern zur Verfügung stehen. Solche internen Klassen deklariert man mit den traditionellen Mitteln als package-visible und legt sie zusammen mit den Klassen, die sie benutzen dürfen, in ein gemeinsames Package. Nun werden die internen sun.*-Klassen aber von so vielen JDK-Klassen verwendet, dass man riesengroße Packages bekommen hätte. Das wollte man natürlich nicht. Also hat man Klassen wie sun.misc.Unsafe notgedrungen public gemacht und sich andere Schutzmechanismen überlegt, um sie der allgemeinen Benutzung zu entziehen. Aber all diese Schutzmechanismen lassen sich aushebeln, sodass Klassen wie sun.misc.Unsafe heute de facto keine internen JDK-Klassen mehr sind, sondern in allen möglichen Anwendungen und Bibliotheken benutzt werden, die sie eigentlich gar nicht benutzen dürfen. Mit anderen Worten, die traditionellen Kapselungsmechanismen bieten keinen ausreichenden Schutz. Das wird sich mit dem Modulsystem ändern.

Ein anderes Problem mit den traditionellen Mechanismen ist die so genannte JAR Hell. In größeren Applikationen kommt es immer wieder vor, dass eine bestimmte Third-Party-Bibliothek von verschiedenen Teilen der Applikation in verschiedenen Versionen benötigt wird. Nun kann man zwar die JAR-Dateien für die beiden Versionen der Bibliothek auf den Classpath legen, aber es wird beim Classloading später die Klasse aus der JAR-Datei genommen, die als erste auf dem Classpath gefunden wurde. Es ist mit den traditionellen Mitteln nicht möglich zu spezifizieren, welche Komponenten in welcher Version von wem gebraucht werden. Auch das wird sich mit den Modulen ändern.

Ein anderes Problem ist die Größe der Anwendungen. Das JDK z. B. ist von Release zu Release immer größer geworden. Mit den traditionellen Mechanismen gibt es jedoch keine Möglichkeit, partielle JDK Deployments zu machen. Diese und andere Gründe haben dazu geführt, dass ein Modulsystem für Java mit besseren Kapselungsmechanismen erforderlich ist.

Das modularisierte JDK

Als Erstes hat man bei Oracle das JDK reorganisiert und in Module zerlegt. Dafür hat man rund fünf Jahre gebraucht. Die tatsächlichen Beziehungen sind noch deutlich komplexer; man kann sich das komplette Diagramm im JEP 200: The Modular JDK anschauen [2].

Welche Auswirkungen hat die Modularisierung des JDK für die Java-Entwickler? Im günstigsten Falle merken wir als Entwickler fast gar nichts davon, und unsere Anwendung läuft mit dem modularisierten JDK 9 genauso wie mit dem alten JDK 8. Es kann aber auch sein, dass beim Umstieg auf Java 9 Anpassungen an der eigenen Applikation gemacht werden müssen. Das ist beispielsweise in folgenden Fällen nötig:

  • Die Anwendung verwendet JDK-interne APIs aus den sun.*-Packages. Diese internen Klassen sind im modularisierten JDK nun wirklich intern und nicht mehr zugänglich.

  • Die Anwendung ist in irgendeiner Form abhängig vom Deployment des JDK oder des JRE, z. B. wenn direkt auf die rt.jar-Datei zugegriffen wird. Diese Datei gibt es nicht mehr.

  • Die Anwendung wertet den Java-Version-String aus. Das wird wahrscheinlich nicht mehr funktionieren, denn die Syntax der Versionsbezeichnungen hat sich geändert.

  • Die Anwendung verwendet sogenannte Split-Packages. Das kommt vor, wenn die Anwendung APIs benutzt, die in einer Third-Party-Software nicht public, sondern nur package-visible sind. Um an die package-visible-APIs heranzukommen, muss man die benutzenden eigenen Klassen in dem betreffenden fremden Package definieren. So etwas geht mit Modulen nicht mehr.

Die Liste ist nicht vollständig. Es gibt noch mehr Szenarien, in denen Anpa...

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