Das Java Development Kit 17 [JDK17] ist am 14. September 2021 als Produktionsrelease fällig und wird als Long-Term-Support (LTS)-Release mit erweitertem Support für mehrere Jahre von verschiedenen Herstellern erwartet. Der Funktionsumfang wurde am 10. Juni eingefroren, als JDK 17 eine erste Rampdown-Phase erreichte.
Einige der Funktionen, die als Teil von OpenJDKs JDK 17 eingereicht wurden, stelle ich im Folgenden vor.
Kontextspezifische Deserialisierungsfilter
„Context-Specific Deserialization Filters” (JEP 415) ermöglichen es Anwendungen, kontextspezifische und dynamisch ausgewählte Deserialisierungsfilter über eine JVM-weite „Filterfactory” zu konfigurieren, die aufgerufen wird, um einen Filter für jeden Serialisierungsvorgang auszuwählen.
Als Motivation hinter diesem Vorschlag weist Oracle darauf hin, dass das Deserialisieren nicht vertrauenswürdiger Daten eine von Natur aus gefährliche Aktion ist, da der Inhalt der eingehenden Datenströme die erstellten Objekte, die Werte ihrer Felder und die Verweise zwischen ihnen bestimmt. Bei vielen Anwendungen werden die Bytes im Stream von einem unbekannten, nicht vertrauenswürdigen oder nicht authentifizierten Client ohne weitere Prüfung empfangen und verarbeitet. Bei gezielter Konstruktion des Streams kann ein Angriff dazu führen, dass Code in beliebigen Klassen mit böswilliger Absicht ausgeführt wird. Wenn die Objektkonstruktion Nebenwirkungen hat, die den Status ändern oder andere Aktionen auslösen, können diese Aktionen die Integrität von Anwendungsobjekten, Bibliotheksobjekten und der Java-Laufzeit kompromittieren. Die Idee zum Deaktivieren von Serialisierungsangriffen besteht darin, zu verhindern, dass Instanzen beliebiger Klassen deserialisiert werden, wodurch die direkte oder indirekte Ausführung ihrer Methoden verhindert wird.
Deserialisierungsfilter wurden in Java 9 eingeführt, damit der Anwendungs- und Bibliotheksquelltext eingehende Datenströme validieren kann, bevor diese deserialisiert werden. Das Projekt stellt die Validierungslogik als eine Implementierung von java.io. ObjectInputFilter bereit, und es wird eingesetzt, wenn ein Deserialisierungs-Stream erstellt wird.
Um sich nicht darauf verlassen zu müssen, dass der Ersteller eines Streams explizit eine Validierung anfordert, wurde das JDK Enhancement Proposal 290 erstellt. In diesem JEP wird definiert, dass es einen JVM-weiten Deserialisierungsfilter geben wird, der über eine Programmierschnittstelle, Systemeigenschaften oder Sicherheitseigenschaften eingestellt werden kann. Dieser Ansatz hat jedoch auch Grenzen, insbesondere bei komplexen Anwendungen.
Ein besserer Ansatz besteht darin, Filter pro Stream so zu konfigurieren, dass sie nicht die Teilnahme jedes Streamerstellers erfordern. Die geplante Erweiterung soll Entwicklern dabei helfen, geeignete Filter für jeden Deserialisierungskontext und Anwendungsfall zu erstellen und anzuwenden.
Gleitkomma-Semantik
Mit dem JDK 17 wird es wieder ausschließlich eine strenge Gleitkomma-Semantik geben. Dadurch wird die ursprüngliche Gleitkomma-Semantik der Sprache und der JVM wiederhergestellt (Restore Always-Strict Floating-Point Semantics, JEP 306), die der Semantik vor der Einführung des strikten und standardmäßigen Gleitkomma-Modus in der Java Standard Edition 1.2 entspricht. Zu den Zielen dieser Bemühungen gehört die Erleichterung der Entwicklung numerisch sensibler Bibliotheken, einschließlich java.lang.Math
und java.lang.StrictMath
.
Security Manager
Seit Java 1.0 ist der Security Manager das wichtigste Mittel zum Sichern von clientseitigem Java-Code, er wurde selten zum Sichern von serverseitigem Code verwendet. Ein Ziel des Vorschlags „Deprecate the Security Manager for Removal” (JEP 411) ist die Bewertung, ob neue APIs oder Mechanismen erforderlich sind, um bestimmte klar definierte Anwendungsfälle zu adressieren, für die der Security Manager verwendet wurde, wie das Blockieren von System::exit. Es ist geplant, den Security Manager zusammen mit dem alten Applet-API zu entfernen, das ebenfalls in JDK 17 als deprecated markiert werden wird.
Mustervergleich für switch
„Pattern Matching for switch (Preview, JEP 406)” erweitert die Sprache Java. Hiermit soll es ermöglicht werden, switch-Ausdrücke und -Anweisungen gegen eine Reihe von Mustern zu testen, jedes mit einer bestimmten Aktion. Damit lassen sich komplexe datenorientierte Anfragen prägnant und sicher formulieren.
Zu den Zielen dieser Funktion gehört es, die Aussagekraft und Anwendung von switch-Ausdrücken und -Anweisungen zu erweitern, indem Muster in „case”-Labels angezeigt werden. Zusätzlich wird die historische Null-Feindlichkeit von switch gelockert, wenn gewünscht, und es werden zwei Arten von Mustern eingeführt:
- bewachte Muster (guarded patterns), die eine Verfeinerung der Mustervergleichslogik mit beliebigen booleschen Ausdrücken ermöglichen, und
- geklammerten Muster (parenthesized patterns), die einige Parsing-Mehrdeutigkeiten auflösen.
Im JDK 16 [Kill21] wurde bereits der instanceof-Operator erweitert, um ein Typmuster (type pattern) zu verwenden und einen Mustervergleich (pattern matching) durchzuführen. Die vorgeschlagene kleine Erweiterung ermöglicht eine Vereinfachung des bekannten instanceof-and-cast-Idioms.
Starke Kapselung für JDK-Interna
Eine starke Kapselung für JDK-Interna [JEP403], mit Ausnahme kritischer interner APIs wie zum Beispiel sun.misc.Unsafe, wird es nicht mehr möglich machen, die starke Kapselung interner Elemente über eine einzige Befehlszeilenoption wieder zugänglich zu machen, was vom JDK 9 bis hin zum JDK 16 möglich gewesen ist. Hiermit soll erreicht werden, dass sowohl die Sicherheit als auch Wartbarkeit der JDK/JVM-Quelltexte erhöht wird. Ebenfalls möchte man die Entwickler dahin bekommen, die eigenen Projekte derart zu migrieren, dass nur noch Standard-APIs eingesetzt werden.
Aufruf entfernter Methoden
Im JDK 17 wird der Aktivierungsmechanismus für Remote Method Invocation (RMI) unter Beibehaltung der restlichen Funktionalitäten von RMI entfernt (JEP 407). Der RMI-Aktivierungsmechanismus ist veraltet, wird nicht mehr verwendet und wurde schon im JDK 15 für die Entfernung aus dem JDK freigegeben.
Foreign Function & Memory
Mit der Programmierschnittstelle „Foreign Function & Memory” (JEP 412) bekommen wir eine Schnittstelle, mit der Java-Programme mit Code und Daten außerhalb der Java-Laufzeit zusammenarbeiten können. Durch effizientes Aufrufen fremder Funktionen (d. h. Code außerhalb der JVM) und sicheren Zugriff auf fremden Speicher (d. h. Speicher, der nicht von der JVM verwaltet wird) ermöglicht das API Java-Programmen, native Bibliotheken aufzurufen und native Daten, ohne die Brüchigkeit und Gefahr von JNI.
Vector
Mit dem Vektor-API (JEP 414) soll es möglich sein, Vektorberechnungen auszudrücken, die zuverlässig zur Laufzeit zu optimalen Vektoranweisungen auf unterstützten CPU-Architekturen kompilieren und so eine Leistung erzielen, die vergleichbaren skalaren Berechnungen überlegen sein soll. Im JDK 17 wurde das Vektor-API hinsichtlich Leistung und Implementierung verbessert, einschließlich Verbesserungen zum Übersetzen von Bytevektoren in und aus booleschen Arrays.
Sealed Classes
Durch die Einführung der „sealed classes/interfaces” (JEP 409) wird es einen neuen Mechanismus innerhalb der Vererbung von Java geben. Bei diesen Elementen kann man einschränken, welche anderen Klassen oder Schnittstellen diese erweitern oder implementieren können. Zu den Zielen des Vorschlags gehört es, dem Autor einer Klasse oder Schnittstelle die Kontrolle darüber zu geben, welcher Code für die Implementierung verantwortlich ist, eine deklarativere Möglichkeit als Zugriffsmodifikatoren bereitzustellen und die Verwendung einer Superklasse einzuschränken.
Entfernung des experimentellen AOT- und JIT-Compilers
Der experimentelle AOT- und JIT-Compiler wird nur wenig verwendet, erfordert aber einen erheblichen Wartungsaufwand in der Entwicklung. Der Plan (JEP 410) sieht die Wartung der JVM-Compilerschnittstelle auf Java-Ebene vor, damit Entwickler weiterhin extern erstellte Versionen des Compilers für die JIT-Kompilierung verwenden können. Die AOT-Compilierung (das jaotc-Tool) wurde in das JDK 9 integriert als experimentelle Funktion deklariert. Das Tool selbst verwendet den Graal-Compiler für die AOT-Compilierung, der wiederum selbst in Java geschrieben ist.
Nach dem angedachten Plan würden drei JDK-Module entfernt:
- jdk.aot (das jaotc-Tool),
- jdk.internal.vm.compiler (der Graal-Compiler) und
- jdk.internal.vm.compiler.management (die Graal MBean).
Der HotSpot-Quelltext im Zusammenhang mit der AOT-Compilierung wird dann ebenfalls entfernt.
MacOS/AArch64
JEP 391 sieht die Portierung des JDK auf macOS/AArch64 vor als Reaktion auf Apples Plan, seine Macintosh-Computer von x64 auf AArch64 umzustellen. Für Linux existiert bereits eine AArch64-Portierung für Java und für Windows wird derzeit noch daran gearbeitet.
Applet-API
Das Applet-API wird als deprecated (JEP 398) versehen mit dem Zusatz, dass es entfernt werden wird. Dieses API ist im Wesentlichen irrelevant, da alle Webbrowser-Anbieter entweder die Unterstützung für Java-Browser-Plug-ins eingestellt oder dies angekündigt haben. Das Applet-API war zuvor als deprecated, aber noch nicht zum Entfernen vorgesehen.
Rendering-Pipeline für MacOS
Eine neue Rendering-Pipeline für MacOS wird es geben (JEP 382), die das Apple Metal-API als Alternative zur vorhandenen Pipeline verwendet, die wiederum das veraltete OpenGL-API verwendet. Dieser Vorschlag soll eine voll funktionsfähige Rendering-Pipeline für das Java 2D-API bereitstellen, das das MacOS Metal-Framework verwendet, und bereit sein, falls Apple das OpenGL-API aus einer zukünftigen Version von MacOS entfernt.
Die Pipeline soll funktionale Parität mit der bestehenden OpenGL-Pipeline aufweisen und in ausgewählten Anwendungen und Benchmarks eine ebenso gute oder bessere Leistung aufweisen. Es wird damit eine saubere Architektur geschaffen, die in das aktuelle Java-2D-Modell passt. Die Pipeline wird mit der OpenGL-Pipeline koexistieren, bis diese als deprecated eingestuft wird. Es ist nicht Ziel des Vorschlags, neue Java- oder JDK-APIs hinzuzufügen.
Pseudozufallszahlengeneratoren
Verbesserte Pseudozufallszahlengeneratoren (JEP 356), die neue Schnittstellentypen und Implementierungen für Pseudozufallszahlengeneratoren (PRNGs) bereitstellen, einschließlich „jumpable” PRNGs und einer zusätzlichen Klasse „splittable” PRNG-Algorithmen (LXM). Eine neue Schnittstelle, RandomGenerator, wird ein einheitliches API für alle bestehenden und neuen PRNGs bereitstellen. Vier spezialisierte RandomGenerator-Schnittstellen werden hierfür bereitgestellt.
Die Motivation des Plans liegt in dem Fokus auf mehrere Verbesserungsbereiche im Bereich der Pseudozufallszahlengenerierung in Java. Der Aufwand erfordert nicht die Bereitstellung von Implementierungen zahlreicher anderer PRNG-Algorithmen. Es werden jedoch drei gängige Algorithmen hinzugefügt, die bereits in anderen Programmiersprachenumgebungen weit verbreitet sind. Zu den Zielen des Plans gehören:
- Erleichterung der austauschbaren Verwendung verschiedener PRNG-Algorithmen in Anwendungen.
- Verbesserte Unterstützung für streambasierte Programmierung, die Streams von PRNG-Objekten bereitstellt.
- Eliminierung von Codeduplizierung in bestehenden PRNG-Klassen.
- Bewahrung des bestehenden Verhaltens der Klasse java.util.Random.
Fazit
Alles zusammen sind das sehr spannende Erweiterungen. Es handelt sich hierbei ja wieder um ein LTS-Release, daher ist dann zu erwarten, dass die Projekte, die auf dem JDK8 oder JDK11 stehen, migrieren werden. Ich werde in dieser Kolumne in den nächsten Ausgaben detailliert auf die jeweiligen Neuerungen eingehen und dabei das Thema der Migration beleuchten. Wer möchte, kann natürlich auf meinem Youtube-Kanal vorbeischauen, da wird es in den nächsten Wochen/Monaten einige Updates zu diesem Thema geben.
Bis dahin, happy coding
Cheers Sven
Weitere Informationen
[JDK17]
https://openjdk.java.net/projects/jdk/17/
[JEP403]
JDK Enhancement-Proposal 403: Strongly Encapsulate JDK Internals, https://openjdk.java.net/jeps/403
[Kill21]
P. Kill, IDG Communications, Inc., 16.3.2021, https://www.infoworld.com/article/3569150/jdk-16-the-new-features-in-java-16.html
Youtube-Kanal
Wer sich den Artikel auf Youtube ansehen möchte, der kann auf meinem Youtube-Kanal das Video unter https://bit.ly/Youtube-Sven finden. Gerne begrüße ich Dich dort als meinen neuen Subscriber.