(Bild: Natalia Hanin / Shutterstock.com)
Gerade ist das OpenJDK 24 mit 24 Java Enhancement Proposals erschienen. Dabei ist einiges unter der Haube passiert, und es gibt neue Sicherheitsfunktionen.
In einem früheren Post [1] haben wir uns bereits die zehn, insbesondere für Entwicklerinnen und Entwickler relevanten Neuerungen angeschaut. In diesem zweiten Teil werfen wir einen Blick auf die restlichen JEPs.
Viele Neuerungen beziehen sich auf Themen unter der Haube (z. B. Garbage Collector), auf Optimierungen beim Start bzw. im laufenden Betrieb von Java-Anwendungen und Maßnahmen, die die Robustheit der Java-Plattform steigern. So erhält im JEP 404 der Shenandoah Garbage Collector ähnlich wie der Z Garbage Collector (ZGC) einen "Generational Mode". Dabei wird zwischen neuen und alten Objekten unterschieden. Die junge Generation enthält eher kurzlebige Objekte und wird häufiger bereinigt. Die alte Generation muss dagegen nur selten aufgeräumt werden. Damit verbessert sich der Durchsatz sowie die Widerstandsfähigkeit gegen Lastspitzen, und die Speichernutzung wird optimiert. Beim Z Garbage Collector wird mit dem JEP 490 der nicht generationale Modus nun entfernt, da der generationale Modus inzwischen leistungsfähiger und für die meisten Anwendungen besser geeignet ist. Die Maßnahme soll den Wartungsaufwand reduzieren und die Weiterentwicklung des generationalen Modus beschleunigen. Das reflektiert den Fokus auf modernere Ansätze bei der Speicherbereinigung, die sowohl Effizienz als auch Wartbarkeit erhöhen sollen.
Der JEP 475 (Late Barrier Expansion for G1) führt eine Optimierung für den Standard Garbage Collector G1 ein, indem Speicherbarrieren später im Kompilierungsprozess generiert werden. Diese Änderung verbessert die Qualität der maschinennahen Instruktionen, reduziert die Komplexität in der Implementierung und erleichtert die Pflege. Die Motivation liegt in der Identifizierung von Schwächen bei der bisherigen Platzierung von Barrieren, insbesondere im Hinblick auf ihren Einfluss auf die Leistung und den Speicherverbrauch. Durch diese spätere Platzierung können unnötige Barrieren eliminiert werden, was zu einer effizienteren Programmausführung beiträgt. Diese Optimierung stellt einen weiteren Schritt dar, die Performance und Wartbarkeit des G1-Garbage-Collectors zu verbessern und langfristig die Anpassungsfähigkeit an moderne Hardwarearchitekturen sicherzustellen.
Der JEP 450 führt kompakte Objekt-Header in Java ein, um Speicherplatz effizienter zu nutzen und den Speicherverbrauch von Java-Objekten zu reduzieren. Der Header, der bisher 128 Bit auf 64-Bit-Plattformen einnahm, wird auf 64 Bit verkleinert. Das geschieht durch komprimierte Klassenreferenzen und eine optimierte Verwaltung von Synchronisierungsinformationen. Der Ansatz zielt darauf ab, die Speicherbelastung bei datenintensiven Anwendungen mit vielen kleinen Objekten zu minimieren, ohne die Leistung der JVM zu beeinträchtigen. Da jedoch tiefgreifende Änderungen an grundlegenden Datenstrukturen vorgenommen werden, bleibt das Feature zunächst experimentell, um mögliche Probleme zu identifizieren und Feedback zu sammeln. Dies könnte langfristig die Grundlage für eine noch effizientere Speicherverwaltung in zukünftigen Java-Versionen schaffen.
Der JEP 483 führt das Konzept des Ahead-of-Time (AOT) Class Loading & Linking ein, das die Startzeit und die Effizienz von Java-Anwendungen verbessern soll. Die Idee besteht darin, häufig genutzte Klassen bereits zur Build-Zeit vorzubereiten, statt sie erst zur Laufzeit zu laden und zu verlinken. Das geschieht durch die Integration einer AOT-Caching-Lösung, in der Metadaten wie Konstanten, Methoden-Handles oder Lambda-Ausdrücke vorgeladen und gespeichert werden. Ziel ist es, die Kosten und Latenzen des dynamischen Ladens zur Laufzeit zu minimieren, was insbesondere bei wiederkehrenden Anwendungsfällen in Cloud-nativen oder ressourcenbeschränkten Umgebungen Vorteile bringt. Die Motivation hinter dieser Änderung liegt in der zunehmenden Bedeutung von schnell startenden Anwendungen, die oft auf Containerplattformen wie Kubernetes ausgeführt werden. In solchen Umgebungen ist die Optimierung von Startzeiten und Speicherverbrauch entscheidend. Durch die Verwendung eines Cache-Mechanismus wird die Effizienz deutlich gesteigert, ohne die Flexibilität des Java-Ökosystems zu beeinträchtigen.
JEP 491 verbessert die Skalierbarkeit von Java-Anwendungen, die synchronized-Methoden und -Blöcke verwenden. Derzeit führt das Synchronisieren von virtuellen Threads dazu, dass auch die darunter liegenden Plattform-Threads blockiert werden. Viele parallel existierende virtuelle Threads können ihre Vorteile nicht mehr ausspielen, und das kann die Performance und Skalierbarkeit erheblich beeinträchtigen. Bei der Einführung der Virtual Threads in Java 21 ist man diesen Kompromiss bewusst eingegangen, um sie möglichst schnell auf die Straße bringen zu können. Mit dem JEP 491 wurde die Architektur der virtuellen Threads aber nun nochmals angepasst. Threads, die auf Monitore warten, können den zugrunde liegenden Plattform-Thread nun wieder freigeben, ohne die Funktionalität von synchronized zu beeinträchtigen. Das bedeutet, dass virtuelle Threads, die in synchronized-Blöcke eintreten oder darauf warten, nicht mehr die zugehörigen Plattform-Threads blockieren, wodurch die Anzahl der verfügbaren virtuellen Threads für die Bearbeitung von Aufgaben maximiert wird. Diese Änderungen wird die Effizienz bei der Nutzung von virtuellen Threads erheblich steigern. Es werden jetzt fast alle Fälle von Thread-Pinning vermieden, die bisher die Skalierbarkeit begrenzt haben.
JEP 478 führt eine API für Key Derivation Functions (KDFs) als Preview ein, um sichere Ableitungen von kryptografischen Schlüsseln zu unterstützen. Diese werden aus einem geheimen Schlüssel und zusätzlichen Informationen generiert, basierend auf Standards wie RFC 5869 (HMAC-based Extract-and-Expand Key Derivation Function, HKDF). Ziel ist es, eine standardisierte, gut integrierte Lösung für Java-Entwickler bereitzustellen, die interoperabel und vielseitig einsetzbar ist. Bestehende Methoden für Verschlüsselung, Authentifizierung und digitale Signaturen beruhen oft auf benutzerdefinierten Implementierungen, die potenziell unsicher oder weniger effizient sind. Die API bietet ein standardisiertes Framework, das die Sicherheit und Benutzerfreundlichkeit erhöht, während es gleichzeitig mit den aktuellen Sicherheitsbibliotheken von Java kompatibel bleibt.
Die JEPs 496 (Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism – ML-KEM) und 497 (Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm – ML-DSA) führen Implementierungen von Algorithmen für Schlüsselaustauschverfahren und digitale Signaturen ein. ML-KEM ist ein von NIST (National Institute of Standards and Technology) in FIPS 203 (Federal Information Processing Standard) standardisierter Algorithmus, der sichere Schlüsselaustauschverfahren gegen zukünftige Angriffe durch Quantencomputer ermöglicht. Dies ist besonders relevant, da Quantencomputer herkömmliche kryptografische Verfahren wie RSA und Diffie-Hellman in Zukunft brechen werden. Java 24 unterstützt ML-KEM mit den Parametern ML-KEM-512, ML-KEM-768 und ML-KEM-1024, um die Sicherheit von Anwendungen langfristig zu gewährleisten. ML-DSA ist ein von NIST in FIPS 204 standardisierter Algorithmus zur digitalen Signatur, der ebenfalls gegen zukünftige Angriffe durch Quantencomputer abgesichert ist. Digitale Signaturen werden zur Authentifizierung und zur Erkennung von Datenmanipulationen genutzt. Java 24 unterstützt ML-DSA mit den Parametern ML-DSA-44, ML-DSA-65 und ML-DSA-87, um eine langfristig sichere Signaturprüfung zu ermöglichen.
Der JEP 472 (Prepare to Restrict the Use of JNI) zielt darauf ab, die Nutzung der Java Native Interface (JNI) zu beschränken, um die Integrität und Sicherheit der Java-Plattform zu erhöhen. JNI erlaubt den Zugriff auf private Felder und Methoden sowie den direkten Speicherzugriff, was grundlegende Prinzipien wie Kapselung und Speichersicherheit untergräbt. Ziel ist es, die Verwendung von JNI standardmäßig einzuschränken, es jedoch für Anwendungen explizit aktivieren zu können, die es benötigen. Dies folgt dem langfristigen Ansatz, Java von unsicheren APIs zu befreien und alternative Mechanismen wie die Foreign Function & Memory API zu fördern. Die Motivation liegt in der Verbesserung der Robustheit, Wartbarkeit und Sicherheit der Plattform, um Risiken wie Speicherkorruption und unvorhergesehenes Verhalten zu minimieren und die Modernisierung von Java-Programmen zu erleichtern.
Der JEP 479 (Remove the Windows 32-bit x86 Port) entfernt den Windows 32-Bit-x86-Port aus dem OpenJDK, da diese Architektur zunehmend veraltet ist und keine neue Hardware mit diesem Format mehr produziert wird. Windows 10, das letzte Betriebssystem mit Unterstützung für 32-Bit-Betrieb, erreicht 2025 das Ende seines Lebenszyklus, was die Relevanz dieser Plattform weiter verringert. Durch das Entfernen dieses Ports können Ressourcen bei der Weiterentwicklung von Java effizienter genutzt werden. Gleichzeitig wird die Wartung durch die Reduzierung von Komplexität vereinfacht. Diese Änderung entspricht den aktuellen Trends in der Industrie, bei der 64-Bit-Architekturen klar dominieren. Anwender können weiterhin ältere Versionen des JDK nutzen oder durch den Einsatz von Remote-APIs für 32-Bit-Funktionen migrieren. Neben Windows müssen bald auch andere 32-bit-Implementierungen dran glauben: Mit dem JEP 501 (Deprecate the 32-bit x86 Port for Removal) wird der 32-Bit-x86-Port in Java 24 als veraltet markiert und auf dessen Entfernung in einer zukünftigen Version vorbereitet. Betroffen ist insbesondere die letzte verbliebene Implementierung für Linux auf 32-Bit-x86. Die Wartung dieses Ports verursacht ebenfalls hohe Kosten und blockiert die Implementierung neuer Features wie Project Loom, das Foreign Function & Memory API oder die Vector API. Nach der Entfernung bleibt als einzige Möglichkeit zur Ausführung von Java-Programmen auf 32-Bit-x86-Prozessoren der architekturunabhängige Zero-Port.
Durch den JEP 498 (Warn upon Use of Memory-Access Methods in sun.misc.Unsafe) gibt Java 24 eine Laufzeitwarnung aus, wenn erstmals eine der unsicheren Speicherzugriffsmethoden in sun.misc.Unsafe aufgerufen wird. Diese Methoden wurden bereits in JDK 23 zur Entfernung markiert. Sie wurden durch sicherere Alternativen ersetzt, z. B. VarHandle (JEP 193, JDK 9) für Speicherzugriffe auf dem Heap und MemorySegment (JEP 454, JDK 22) für Off-Heap-Speicher. Das Ziel ist es, Entwickler frühzeitig auf die Entfernung dieser Methoden in zukünftigen JDK-Versionen vorzubereiten und sie zum Umstieg auf standardisierte APIs zu bewegen.
Mit dem JEP 493 (Linking Run-Time Images without JMODs) wird die Größe einer vom Benutzer erstellten Laufzeitumgebung (JRE) mit jlink um etwa 25 % verringert. Bei der Erzeugung der Images werden keine JMOD-Dateien inkludiert. Diese Funktion muss allerdings bei der Erstellung des JDKs aktiviert werden. Und einige JDK-Anbieter entscheiden sich möglicherweise dafür, diese Option nicht umzusetzen. Als Motivation wird darauf verwiesen, dass in Cloud-Umgebungen die installierte Größe des JDK auf dem Dateisystem wichtig ist. Gerade Container-Images, die ein installiertes JDK enthalten, werden automatisch und häufig über das Netzwerk aus Container-Registries kopiert heruntergeladen. Eine Verringerung der Größe des JDK würde die Effizienz dieser Vorgänge verbessern.
Java 24 ist ein spannendes Release mit vielen neuen Features – auch wenn für uns Entwickler auf den ersten Blick scheinbar gar nicht so viel Neues dabei ist. Vieles sind Wiedervorlagen aus früheren Preview-Versionen. Aber genau das zeigt, wie stabil und durchdacht sich Java weiterentwickelt. Und außerdem ist enorm viel unter der Haube passiert: von Performance-Optimierungen über Sicherheitsverbesserungen bis hin zu Weichenstellungen für die Zukunft, etwa in der Kryptografie und der Speicherverwaltung. Java bleibt damit eine moderne, leistungsfähige Plattform. Und im September 2025 steht mit dem OpenJDK 25 die nächste LTS-Version vor der Tür.
Zum Vertiefen der hier genannten Features empfiehlt sich als Startpunkt die OpenJDK 24-Projektseite [2]. Und es gibt natürlich auch eine ausführliche Liste aller Änderungen in den Release Notes [3].
URL dieses Artikels:
https://www.heise.de/-10322221
Links in diesem Artikel:
[1] https://www.heise.de/blog/Java-Rekord-beim-bevorstehenden-Release-des-OpenJDK-24-10051629.html
[2] https://openjdk.org/projects/jdk/24
[3] https://jdk.java.net/24/release-notes
[4] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: Erstellt mit KI (Midjourney) durch iX-Redaktion)
Java wird im Jahr 2025 schon 30 Jahre alt. Das ist ein guter Zeitpunkt, zurück, aber auch nach vorn zu blicken.
Der Softwarearchitekt und -entwickler Adam Bien hat sich in der internationalen Java-Szene einen Namen gemacht. Er ist Java Champion und wurde 2010 zum Java Developer of the Year gekürt [1]. Auf Konferenzen begeistert er seit Jahren sein Publikum und wurde für seine Vorträge unter anderem auf der Java One seit 2009 mehrmals zu den RockStars gewählt.
Adam wird bei der JavaLand 2025 eine Keynote zu 30 Jahren Java [2] halten, und wir haben ihm vorab schon einige Fragen gestellt.
Falk Sippach: Adam, du bist eine Schlüsselfigur in der Java-Community und hast die Evolution der Plattform und der Sprache schon relativ früh bis zur Gegenwart aktiv mitgestaltet. Wann und mit welcher Version bist du erstmals mit Java in Berührung gekommen?
Adam Bien: Ich habe Java kurz vor der Veröffentlichung des JDK 1.0 evaluiert und war nicht begeistert. Ich war damals ein C++-Fan und hatte viel Spaß mit Operator Overloading und Include-Dateien. Beides fehlte mir in Java. Das war etwa 1995.
Falk Sippach: Wenn man sich deine bisherigen Veröffentlichungen (Bücher, Vorträge, Workshops, ...) anschaut, fallen dabei viele relevante Meilensteine des Java-Ökosystems ins Auge. Was waren für dich in deiner Laufbahn die bemerkenswertesten Sprachfeatures, Bibliotheken, Standards und Werkzeuge?
Adam Bien: Alles begann mit Applets. Mein erstes kommerzielles Projekt war ein Chat-Applet mit Remote Method Invocation (RMI) Backend. Aber ich konnte es kaum erwarten, bis Servlets verfügbar wurden. Ich sollte eine serverseitige CMS-Anwendung mit Common Gateway Interface (CGI) implementieren. Ich hatte keine Erfahrung mit CGI und wartete ungeduldig auf die erste Version des JavaWebServers von Sun Microsystems um 1997.
Das nächste Projekt, wieder mit JavaWebServer, war eine E-Commerce-Lösung. Hier haben wir das gesamte Backend mit JavaBeans und JDBC implementiert. Die Produktvielfalt war eine echte Herausforderung. Die Applikationsserver waren kaum vergleichbar und die Programmiererfahrung nicht übertragbar. Mit der Einführung von J2EE wurde dieses Problem durch die Standardisierung der APIs gelöst. Fortan konnte ich produktiv mit verschiedenen Produkten entwickeln.
Die Idee von Quarkus hat mich ebenfalls überrascht. Die APIs beizubehalten und gleichzeitig das Deployment zur Laufzeit zu eliminieren, war revolutionär. In den meisten Projekten haben mir die Patterns bei der "Don't Make Me Think"-Entwicklung geholfen und mir Hunderte von überflüssigen Meetings erspart. Wir haben uns auf die Patterns verlassen, um die Anwendung zu strukturieren und uns auf die Implementierung des Mehrwerts konzentriert.
Falk Sippach: Welche Rolle spielt Java deiner Meinung nach in der modernen Softwareentwicklung, insbesondere im Vergleich zu anderen Sprachen und Technologien?
Adam Bien: Java wird immer einfacher und die Entwicklung immer produktiver. Die Typsicherheit von Java wurde mit der wachsenden Popularität von Ruby on Rails um 2006 belächelt, "Duck Typing" mit zusätzlichen Unit Tests sollte die Produktivität und Lesbarkeit des Codes erhöhen. Daraufhin folgten einige schwer wartbare Projekte, die versuchten, zu Java zurückzukehren. Heute versuchen die meisten Programmiersprachen typsicher zu sein. Selbst JavaScript und Python wollen die Typsicherheit.
Auch ORMs wie JPA wurden als überflüssig abgestempelt – NoSQL sollte agiler und leichter verständlich sein. Heute sind ORMs in JavaScript-Frameworks sehr beliebt. Ich habe das Gefühl, dass alle Java-Hypes, die vor 10 Jahren populär waren, heute in anderen Programmiersprachen zu finden sind.
Es wurde sogar argumentiert, dass Java eine Low-Level-Programmiersprache ist, die unnötig schnell ist. Statt Java sollte man lieber höhere, aber weniger performante Programmiersprachen verwenden. Tatsächlich ist Java sehr schnell. Es ist um Faktoren schneller als JavaScript oder Python und vergleichbar mit C.
Java ist langweilig, gut lesbar und eine "No-Magic"-Programmiersprache mit einem sehr guten Tooling und Ökosystem. Daher eignet sich Java besonders für große Projekte. Neue Java-Features wie die direkte Ausführbarkeit von Quelldateien machen Java auch für kleinere Anwendungen und Scripting interessant.
Falk Sippach: Was hat dich motiviert, Java nahezu 30 Jahre lang die Treue zu halten?
Adam Bien: Anfangs wollte ich möglichst viele Programmiersprachen verwenden. Aufgrund der großen Nachfrage nach Java musste ich diese Strategie schnell aufgeben. Sun Microsystems hat früh auf Standards und Herstellervielfalt gesetzt. Ich habe mich auf Standards konzentriert und konnte inkrementell lernen und Erfahrungen sammeln. Um mich herum wurden viele Frameworks gehypt, eingesetzt und wieder verworfen. Dann kam wieder ein ganz anderes Framework zum Einsatz. Man musste sich die Idiome neu aneignen, die Erfahrung war selten übertragbar.
Erst kürzlich habe ich ein etwa 15 Jahre altes Projekt modernisiert. Es war viel einfacher, als ich dachte. Mit Java konnte ich einfachen und langweiligen Produktionscode schreiben und in meiner Freizeit viel Spaß mit JINI, JavaSpaces, JXTA, RMI, JIRO, FreeTTS, Hazelcast und unzähligen anderen Frameworks haben. Java macht mir immer noch Spaß und meine Kunden sind zufrieden. Ich sehe keinen Grund, zu wechseln. Lediglich im Frontend verwende ich reine "Webstandards" und Web Components gepaart mit reinem JavaScript ohne Abhängigkeiten oder externe Bibliotheken. "The Java way". Auch dieser Ansatz wird übrigens immer populärer.
In den letzten Jahren konnten wir mit Java, Quarkus und serverlosen Architekturen einfache Anwendungen bauen, die im Betrieb sehr kostengünstig, in einigen Fällen sogar kostenlos waren. Sogar die Kommentare zu meinen (>800) YouTube-Shorts sind überraschend positiv – Java ist immer noch sehr populär und viele sind immer noch überrascht von den Java-Features.
Falk Sippach: Welche Tipps kannst du aktuellen Java-Entwicklern geben, um in der sich schnell verändernden Technologielandschaft am Ball zu bleiben und sich mit Java weiterzuentwickeln?
Adam Bien: Hypes wiederholen sich. Das Wichtigste ist, möglichst einfachen Code zu schreiben. Der Mehrwert für den Kunden sollte immer im Vordergrund stehen.
Falk Sippach: Zu guter Letzt wollen wir noch einen Blick in die Zukunft wagen. Welche Herausforderungen und Chancen siehst du für Java in den nächsten fünf bis zehn Jahren?
Adam Bien: In Java gibt es derzeit viele Innovationen. GraalVM ermöglicht die Ausführung von JavaScript, Python und sogar WebAssembly auf der JVM und mit optionaler Übersetzung in Maschinencode, Graal OS sieht aus wie ein "Pure Java"-Kubernetes, Project Babylon ermöglicht die Transformation von Code – auch für den Betrieb auf GPUs, Valhalla hilft mit Performancegewinnen bei der Model Inference, Leyden macht die Dauer von Kaltstarts konfigurierbar. Es sieht also ausgezeichnet aus - vielleicht gibt es bald einen neuen Java-Hype.
Wollt Ihr Adam Bien live erleben, dann kommt auf die JavaLand [3], die vom 1. bis 3. April am Nürburgring stattfindet.
URL dieses Artikels:
https://www.heise.de/-10304215
Links in diesem Artikel:
[1] https://in.relation.to/2010/10/11/adam-bien-java-developer-of-the-year-2010/
[2] https://meine.doag.org/events/javaland/2025/agenda/#agendaId.5162
[3] https://www.javaland.eu/
[4] mailto:rme@ix.de
Copyright © 2025 Heise Medien
(Bild: Natalia Hanin / Shutterstock.com)
Das OpenJDK entwickelt sich rasant weiter. Die Anzahl der JEPs pro halbjährlichen Release steigt. Java gehört auch mit 30 Jahren noch nicht zum alten Eisen.
Für das OpenJDK 24 [1] sind aktuell (Stand: 20.11.2024) schon 24! (in Worten: vierundzwanzig) JEPs eingeplant. Das passt nicht nur zur nächsten Release-Nummer. Das ist auch ein neuer Rekord, seit die Entwicklung 2018 auf die halbjährlichen Release-Zyklen umgestellt wurde. Und die Zahl kann sogar noch weiter wachsen. Denn erst am 5. Dezember startet die Rampdown Phase One mit dem Feature Freeze für die nächste Version. Und weil es diesmal so viele JEPs (JDK Enhancement Proposals) sind, werden wir hier schon mal einen ersten Blick auf die aus Developer-Sicht interessantesten Punkte werfen, die aktuell eingeplant sind. Weitere Details können über die jeweiligen JEPs nachvollzogen werden.
In einem späteren Post schauen wir uns dann die restlichen Features an. Vielleicht kommen ja sogar noch welche hinzu. Wir dürfen also gespannt sein, was in den nächsten zwei Wochen passieren wird.
JEP 485 – Stream Gatherers
Nach zwei Previews erfolgt nun die Finalisierung. Die in Java 8 eingeführte Stream API unterstützt jetzt das Hinzufügen eigener Intermediate Operationen. Dadurch können Daten in Streams nun auf bessere, optimierte Art und Weise transformiert werden als mit den wenigen fest eingebauten Intermediate Operationen bisher. Somit können Stream Pipelines ab sofort flexibler und ausdrucksstärker implementiert werden. Das OpenJDK liefert auch gleich einige neue Operationen mit: fold, mapConcurrent, scan, windowFixed und windowSliding. In Zukunft können relativ einfach weitere folgen.
JEP 484 – Class-File API
Hier erfolgt nun ebenfalls nach zwei Previews die Finalisierung des neuen Standards zum Parsen, Generieren und Transformieren von Java-Bytecode (Class Files) basierend auf der Spezifikation der Java Virtual Machine. In Zukunft können alle JDK-Komponenten auf diese Standard-API migriert werden. Schlussendlich können die JDK-Entwickler dann die interne Kopie und damit die Abhängigkeit zur Drittanbieter-Bibliothek ASM entfernen.
JEP 488 – Primitive Types in Patterns, instanceof, and switch (Second Preview)
Es geht in diesem zweiten Preview um die Erweiterung des Pattern Matching, sodass primitive Datentypen wie int, byte und double in allen Pattern-Kontexten verwendet werden dürfen, also beim instanceof und im switch. Entwickler haben dadurch weniger Limitierungen und Sonderfälle und können primitive und Referenzdatentypen auch im Kontext von Type Patterns oder als Komponenten in Record Patterns austauschbar verwenden. Seit der ersten Preview gibt es keine Änderungen, die JDK-Entwickler wollen aber weiteres Feedback sammeln.
JEP 499 - Structured Concurrency (Fourth Preview)
Bei der Bearbeitung von mehreren parallelen Teilaufgaben erlaubt Structured Concurrency die Implementierung auf eine besonders les- und wartbare Art und Weise. Alternativ konnten Entwickler für diesen Zweck bisher die Parallel Streams, den ExecutorService oder reaktive Programmierung einsetzen. Alles sehr mächtige Ansätze, die aber gerade einfache Umsetzungen unnötig kompliziert und fehleranfällig machen. Structured Conncurrency behandelt Gruppen von zusammengehörigen Aufgaben als eine Arbeitseinheit, wodurch die Fehlerbehandlung sowie das Abbrechen der Aufgaben vereinfacht und die Zuverlässigkeit sowie die Beobachtbarkeit erhöht werden. Änderungen zur letzten Preview gibt es keine. Die Macher des OpenJDK wünschen sich vielmehr weitere Rückmeldungen aus der "realen" Welt.
JEP 487 – Scoped Values (Fourth Preview)
Einführung eines Gültigkeitsbereichs, sodass unveränderliche Daten sowohl in den Aufrufen innerhalb eines Threads als auch in Child-Threads geteilt und verwendet werden können. Scoped Values lassen sich einfacher nachvollziehen, verfolgen aber ähnliche Ziele wie ThreadLocal-Variablen. Sie haben auch einen geringeren Platz- und Zeitbedarf, insbesondere wenn sie zusammen mit virtuellen Threads (JEP 444 [2]) und Structured Concurrency (JEP 480 [3]) verwendet werden. Eine Änderung gibt es diesmal: Die Methoden callWhere() und runWhere() wurden aus der Klasse ScopedValue entfernt. Ihre Funktionalität kann aber noch über ein Objekt der Klasse Carrier aufgerufen werden, welches die Methode where() von ScopedValue zurückliefert. Dadurch wird die API vollständig fluent. Die Funktion call() liefert übrigens ein Ergebnis, während die Prozedur run() nichts zurückgibt.
JEP 489 – Vector API (Ninth Incubator)
Die Vector API ist der Dinosaurier unter den JEPs und nun schon das neunte Mal als Inkubator dabei. Seit Java 16 taucht sie regelmäßig in den Releases auf. Es geht dabei um die Unterstützung der modernen Möglichkeiten von SIMD-Rechnerarchitekturen mit Vektorprozessoren. Single Instruction Multiple Data (SIMD) lässt viele Prozessoren gleichzeitig unterschiedliche Daten verarbeiten. Durch die Parallelisierung auf Hardwareebene verringert sich beim SIMD-Prinzip der Aufwand für rechenintensive Schleifen. Der Grund für die lange Inkubationsphase hängt mit der Abstimmung mit dem Projekt Valhalla zusammen. Man wartet auf die Reformen am Typsystem (JEP 401: Value Classes and Objects [4]). Die Entwickler des JDK wollen vor der Finalisierung der Vector API die derzeitigen wertbasierten Klassen (Referenztypen) in Value Classes (ohne Objektidentität) umwandeln. Das kann noch etwas dauern, denn für das OpenJDK 24 sind die Value Types bisher noch nicht auf dem Plan. Aber immerhin hat Brian Goetz (Java Language Architekt bei Oracle) im Sommer 2024 angekündigt, dass sie beim Projekt Valhalla nach 10 Jahren den Durchbruch in der Implementierung geschafft haben. Hier könnte also mit dem OpenJDK 25 vielleicht schon die erste Preview auftauchen.
JEP 486 – Permanently Disable the Security Manager
Der Security Manager wurde häufig zur Absicherung von clientseitigem Java-Code (Rich-Clients, Applets), aber nur selten für die Server-Seite verwendet. Zudem ist seine Wartung teuer. Mit Java 17 (2021) wurde er als Deprecated for Removal markiert. Nun wird er intern ausgebaut. Er kann jetzt nicht mehr aktiviert werden und andere Klassen der Java-Plattform verweisen nicht mehr darauf. Diese Änderung wird aber vermutlich keine Auswirkungen auf die große Mehrheit der Anwendungen, Bibliotheken und Tools haben. In einer der zukünftigen Java-Versionen wird die Security Manager API endgültig entfernt.
JEP 492 – Flexible Constructor Bodies (Third Preview)
In Konstruktoren dürfen Anweisungen nun bereits vor einem expliziten Konstruktoraufruf (super() oder this()) erscheinen. Diese Anweisungen dürfen zwar nicht auf die zu konstruierende Instanz verweisen, können jedoch Parameter validieren bzw. transformieren oder auf Felder der Oberklasse zugreifen. Die Initialisierung von Feldern vor dem Aufruf eines anderen Konstruktors macht die Klasse zuverlässiger, wenn beispielsweise Methoden überschrieben werden.
JEP 494 – Module Import Declarations (Second Preview)
Dadurch lassen sich jetzt in Java alle exportierten Packages eines Moduls auf einmal importieren. Das vereinfacht die Wiederverwendung modularer Bibliotheken. Es ist übrigens nicht erforderlich, dass der importierende Code selbst in einem Modul enthalten ist. Bei dieser zweiten Preview gibt es zwei Erweiterungen. Einerseits wurden Beschränkungen bei den transitiven Abhängigkeiten vom Modul java.se (eine Art Aggregator-Modul ohne eigene Packages/Klassen) zu java.base aufgehoben. Dadurch kann man nun mit dem Import dieses einen Moduls die gesamte API von Java SE importieren. Außerdem ist es jetzt möglich, dass sogenannte Type-Import-on-Demand-Deklarationen (z. B. import java.util.*) vorherige Modul-Import-Deklarationen überdecken. Wenn beispielsweise die Module java.base und java.sql importiert werden, gäbe es eine Unklarheit beim Verwenden der Klasse Date. Die gibt es als java.util.Date und als java.sql.Date. Durch die on-demand-Deklaration import java.util.* wird in dem Fall java.util.Date verwendet.
JEP 495 – Simple Source Files and Instance Main Methods (Fourth Preview)
Das Ziel ist, Anfängern den Einstieg in Java zu erleichtern und erfahrenen Entwicklerinnen und Entwicklern die Möglichkeit zu geben, kleine Anwendungen einfach bauen und ausführen zu können. Anfänger wie auch Fortgeschrittene müssen sich somit nicht mit den für große Programme konzipierten Sprachfunktionen auseinandersetzen. In dieser vierten Preview soll weiter Feedback gesammelt werden. Unter Beibehaltung der bestehenden Java-Toolchain und nicht mit der Absicht, einen separaten Dialekt für Java einzuführen, lassen sich in simplen Java Source Files, die nur eine vereinfachte main-Methode (ohne Klassen-Deklaration) enthalten, einfache, skriptartige Programme erstellen. Dazu kommt die leichtere Verwendung von Standardein- und -ausgabe durch die neuen statischen Methoden print(), println() und readln() der Klasse java.io.IO. Diese wird zum Teil automatisch importiert, womit die Funktionen einsatzbereit sind.
URL dieses Artikels:
https://www.heise.de/-10051629
Links in diesem Artikel:
[1] https://openjdk.org/projects/jdk/24/
[2] https://openjdk.org/jeps/444
[3] https://openjdk.org/jeps/480
[4] https://openjdk.org/jeps/401
[5] mailto:rme@ix.de
Copyright © 2024 Heise Medien
(Bild: Erstellt mit KI)
Das Open-Source-Projekt JSpecify zielt auf einheitlichen Standard für Null-Annotationen in Java. Beteiligt sind Firmen wie Google, JetBrains und Microsoft.
Vor einem Jahr habe ich bereits über Null-Checks in Java [1] geschrieben. Nach wie vor ist es sinnvoll, Parameter von Methoden und Konstruktoren mit Annotationen bezüglich des Verhaltens von null (z.B. @NonNull) zu versehen. Mittlerweile ist der Support jedoch deutlich besser geworden, da vor Kurzem Version 1.0 von JSpecify [2] erschienen ist. Das möchte ich für ein Update zu dem Thema nutzen.
JSpecify ist ein Open-Source-Projekt [3], in dem sich die bisherigen Anbieter von Null-Handling-Annotationen zusammengeschlossen haben, um endlich einen nutzbaren Standard zu definieren. Dazu gehören unter anderem Google, JetBrains, Meta, Microsoft und Oracle. JSpecify ist ein vollwertiges Modul im Java-Modulsystem, hat keine eigenen Abhängigkeiten und liefert mit gerade einmal vier Annotationen alles, was man in einem modernen Java-Projekt benötigt, um das Handling von null bei Parametern zu spezifizieren. Beispielcode, der die Annotationen nutzt, könnte wie folgt aussehen:
static @Nullable String emptyToNull(@NonNull String x) {
return x.isEmpty() ? null : x;
}
static @NonNull String nullToEmpty(@Nullable String x) {
return x == null ? "" : x;
}
Mehr Codebeispiele finden sich im User-Guide von JSpecify [4].
Das reine Anbringen der JSpecify-Annotation hat allerdings wenig Effekt. Der Compiler übersetzt weiterhin Code, der null an einen mit @NonNull-annotierten Parameter übergibt, und bei der Laufzeit löst der übersetzte Code nicht automatisch eine Exception aus.
Der Vorteil der Annotationen zeigt sich unter anderem im Zusammenspiel mit Entwicklungsumgebungen. IntelliJ kann die Annotations erkennen [5] und Warnungen oder Fehler bei Code anzeigen, der die Annotationen verletzt. Will man auf Nummer sicher gehen und Code mit solchen Problemen überhaupt nicht zulassen, kann man zusätzliche Hilfsmittel verwenden. Das von Uber entwickelte Open-Source-Tool NullAway [6] kann diese Annotationen zur Build-Zeit überprüfen und Fehler auszulösen, wenn die Definition der Annotationen nicht eingehalten wird. Fügt man das Ganze zu seinem Gradle- oder Maven-Build hinzu, erfolgt beim Kompilieren automatisch einen Fehler:
error: [NullAway] passing @Nullable parameter 'null' where @NonNull is required
myMethod(null);
^
Mit dieser Toolchain kann man seinen Code um einiges robuster bekommen und NullPointerExceptions zur Laufzeit vermeiden.
Muss man sich keine Gedanken mehr über NullPointerExceptions machen? So einfach ist es leider nicht. Diese Maßnahmen können nur den eigenen Code überprüfen. Hat man Abhängigkeiten, die keine solchen Annotationen nutzen, kann man nicht wissen, ob man diesen als Parameter null übergeben kann und welches Verhalten dies auslöst. Daher ist es weiterhin wichtig, an verschiedenen Stellen Variablen auf null zu überprüfen.
Wer Libraries oder Code entwickelt, der von anderen Projekten aufgerufen wird, kann nicht sicherstellen, dass Nutzer sich an die definierten Regeln halten und an einen mit @NonNull annotierten Parameter auch wirklich kein null übergeben. Daher ist es wichtig, immer Null-Checks durchzuführen, wenn man den Kontext des eigenen Codes verlässt – egal ob bei eigenen Abhängigkeiten oder bei einer öffentlichen API.
Dazu ist das aus dem OpenJDK stammende java.util.Objects.requireNonNull(obj, message) weiterhin das Mittel der Wahl. Um immer sinnvolle Exceptions zu erstellen, sollte man auf die Variante mit dem Message-Parameter setzen, da das System sonst eine NullPointerException ohne Message wirft. Das Ganze sieht für eine öffentliche API folgendermaßen aus:
public void setName(@NonNull String name) {
this.name = Objects.requireNonNull(name, “name must not be null”);
}
Wer einem performancekritischen Umfeld arbeitet, sollte auf eigene Methoden für die Checks verzichten. Der JIT-Compiler behandelt Objects.requireNonNull(...) durch die Annotation @ForceInline besonders und fügt alle Aufrufe der Methode direkt in die aufrufende Methode ein (inline), um so Performance und Stack-Größe zu optimieren.
Es hat lange gedauert, bis die Java-Community den heutigen Stand erreicht hat und es eine saubere und sinnvolle Bibliothek mit Annotationen bezüglich Null-Handling gibt. Was als JSR305 [7] im Jahr 2006 gestartet und leider schnell wieder fallengelassen wurde, könnte sich nach vielen Problemen mit unterschiedlichsten Annotationen und Umsetzungen zu einem De-facto-Standard wie SLF4J (Simple Logging Facade for Java) entwickeln.
JSpecify geht hier ganz klar den richtigen Weg. Toll wäre es, wenn nun ein Tooling wie beispielsweise NullAway sich durchsetzt und mit einer einfachen Nutzung und Best Practices es quasi jedem Projekt ermöglicht, besser mit null umzugehen. Wer bisher die Annotationen und Tools wie NullAway noch nicht im Einsatz hat, sollte sie ausprobieren. Jetzt ist der richtige Moment, um damit zu starten.
Anmerkung: Parallel zum Schreiben dieses Beitrags ist im OpenJDK mit einem neuen JEP [8] ein besserer nativer Support angekündigt worden. Da es noch einige Zeit dauern wird, bis die im JEP diskutierten Features Einzug in eine LTS Version des OpenJDK haben werden, sind die hier beschriebenen Mittel und Tools weiterhin eine klare Empfehlung. Das JEP bietet aber genug Aspekte, um es zeitnah in einem Artikel genauer zu betrachten.
URL dieses Artikels:
https://www.heise.de/-9820606
Links in diesem Artikel:
[1] https://www.heise.de/blog/Programmiersprache-Java-Null-Fehler-mit-statischer-Analyse-aufspueren-7351944.html
[2] https://jspecify.dev/
[3] https://github.com/jspecify/jspecify
[4] https://jspecify.dev/docs/user-guide/
[5] https://www.jetbrains.com/help/idea/nullable-notnull-configuration.html
[6] https://github.com/uber/NullAway
[7] https://jcp.org/en/jsr/detail?id=305
[8] https://openjdk.org/jeps/8303099
[9] mailto:rme@ix.de
Copyright © 2024 Heise Medien
(Bild: JHVEPhoto/Shutterstock.com)
Oracles fragwürdige Mittel, Lizenzen für ihre OpenJDK-Distribution einzutreiben, gefährden im schlimmsten Fall Java, meinen Hendrik Ebbers und Falk Sippach.
Sicherlich ist es für viele nichts Neues, dass Oracles Lizenzpolitik nicht gerade nutzerorientiert ist. House of Brick ist ein international tätiger Dienstleister, der Firmen bezüglich der verschiedenen Lizenzmodelle von Oracle berät. Dass es dafür ein Geschäftsmodell gibt, sagt schon einiges darüber aus. Genau diese Firma hat nun Informationen darüber veröffentlicht, dass sich eine immer größer werdende Zahl Kunden im Bereich Java-Lizenzen beraten lässt. Diese Unternehmen wurden offenbar von Oracle kontaktiert, da sie Java SE nicht konform nutzen und einen Lizenzvertrag mit Oracle abschließen müssen.
Aber der Reihe nach: Warum benötigt es so einen Vertrag und wie kam Oracle überhaupt an die Informationen zu diesen Firmen?
Oracle hat im April 2019 zwei neue Lizenzmodelle für die Nutzung des Oracle JDK (ihre kommerzielle Java Distribution) eingeführt. Die bis dahin freie Distribution wurde damit kostenpflichtig. Mit dem Release von Java 20 [1] wurde das Lizenzmodell noch einmal angepasst. Oracle führte nach eigener Aussage ein "einfaches, kostengünstiges, monatliches" Java SE-Universal-Abonnement ein. In diesem neuen Modell müssen Nutzer der Java Distribution von Oracle Lizenzgebühren pro Mitarbeiter des Unternehmens bezahlen. Die Unternehmensberatung Gartner schätzte [2] im letzten Jahr, dass das neue Lizenzmodell pro Mitarbeiter zwei- bis fünfmal teurer sein wird, als das bisherige.
Auf Basis dieses neuen Lizenzmodells "klappert" Oracle nun Firmen ab, um möglichst viele Lizenzverträge abzuschließen. Laut House of Brick hat Oracle ein ganzes Team von Mitarbeitern in Indien eingesetzt, welche Organisationen auf der ganzen Welt kontaktieren. Die Firmeninformationen haben sie hierbei über die letzten Monate gesammelt, indem sie die Downloads ihrer eigenen Java Distribution getrackt haben. Unternehmen, die noch nie mit Oracle zusammengearbeitet haben, sind mit dieser plötzlichen Kontaktaufnahme oft überfordert und wenden sich Hilfe suchend an House of Brick. Laut dessen CEO unterbreitet Oracle diesen "Neukunden" ein Angebot, das sie nicht ablehnen können: Wenn diese Firmen direkt das Abo-Modell abschließen, hat der frühere Einsatz nicht lizenzierter Software keine Folgen. Das bedeutet im Grunde, dass eine Firma entscheiden muss: gehen sie einen Vertrag mit Oracle ein oder nehmen sie das Risiko in Kauf, dass sie gerichtlich zur Nachzahlung von einem solchen Abonnement gezwungen werden.
Soweit die Fakten, welche man auch bei The Register [3] oder im Blog von House of Brick [4] nachlesen kann. Bedeutet das aber nun, dass die Nutzung von Java in Zukunft an ein Abo-Modell bei Oracle geknüpft ist? Natürlich nicht und im Folgenden möchten wir unsere persönliche Sicht der Dinge darlegen. Wir sind sehr besorgt über die jüngsten Entwicklungen hinsichtlich der Lizenzierungspraxis von Oracle für ihre kommerzielle Java Distribution. Dieses Vorgehen kann ein nachhaltig negatives Licht auf die Programmiersprache Java und ihre Laufzeitumgebung werfen. Auch wenn die meisten Entwickler verstehen, dass es sich hier nur um die von Oracle bereitgestellte Distribution von Java handelt, haben Manager und Entscheider oft nicht diesen tiefen Einblick. Anstelle Geld mit Java zu verdienen, kann Oracles Taktik im schlimmsten Fall dazu führen, dass sich Firmen in Zukunft ganz von Java verabschieden.
Diese Geschichte zeigt auch, wie verzweifelt Oracle versucht, mit Java Geld zu machen. Mit der Übernahme von Sun Microsystems im Jahr 2009 haben sie Java erworben und sie sind heute der größte Contributor des OpenJDK. Auch die Namensrechte für das OpenJDK und Java liegen bei Oracle. Basierend auf den aktuellen Ereignissen fragen wir uns nun, was Oracle als Nächstes probieren wird, falls die aktuellen Bemühungen nicht den ausreichenden Erfolg bringen. Wir gehen stark davon aus, dass sie durch diese Vorgehensweise keine nachhaltigen und aus Kundensicht sinnvollen Lizenzverträge für Java abschließen werden. Und vielleicht beschließt ein Manager bei Oracle dann, die Mittel für das OpenJDK zu kürzen. Das wäre etwas, das die ganze Java Community betreffen würde. Am Beispiel von JavaScript sieht man [5], wie Oracle als Besitzer des Trademarks auch auf sein Markenrecht pocht, obwohl sie keinerlei Entwicklungsaktivitäten in dieser Sprache betreiben.
Und nein, wir haben kein Problem damit, wenn Oracle Geld mit dem OpenJDK, Java oder der kommerziellen Java Distribution verdient. Aber wir stellen die Frage, ob dieses Vorgehen wirklich gesund und nachhaltig für das Produkt und die Community ist. Daher wünschen wir uns von Oracle, Transparenz und Fairness bei ihren Lizenzierungsprozessen zu gewährleisten. Unternehmen, die die Java Distribution von Oracle nutzen, sollten klar und deutlich über die Lizenzforderungen informiert werden, bevor sie zu kostenpflichtigen Modellen wechseln müssen.
An alle Entscheider: Es gibt mehrere hochqualitative und kostenfreie Open-Source-Alternativen [6] zur kommerziellen Java Distribution von Oracle, wie beispielsweise Temurin von Eclipse Adoptium, Corretto von Amazon [7] und andere. Diese Alternativen bieten ähnliche Funktionen und langfristige Unterstützung ohne kommerzielle Lizenzgebühren. Verantwortliche können hier die Unterstützung und Ressourcen der Java-Community nutzen und auf Experten in diesem Bereich (z. B. Open Elements [8]) zurückgreifen.
Das Ziel von Adoptium ist es beispielsweise, zertifizierte und für alle Arten von Anwendungen geeignete Java-Builds zu entwickeln und zu verteilen, ohne dass zusätzliche Lizenzgebühren anfallen. Da alle Arbeiten bei Adoptium in der Eclipse Foundation [9] durchgeführt werden, ist Temurin nicht nur herstellerunabhängig, sondern auch deutlich transparenter in der Entwicklung und Bereitstellung als die meisten anderen Distributionen. Unternehmen sollten daher eine Migration zu Temurin in Erwägung ziehen. Hierdurch entsteht nicht nur eine hohe Kostenersparnis. Im Bereich Security erhält man durch transparente Prozesse und Audits ein klareres Bild der genutzten Laufzeitumgebung. Temurin hat sich erst neulich Security Audits unterzogen und die Ergebnisse öffentlich bereitgestellt [10].
Korrektur bezüglich der Arbeit von Oracle im JavaScript-Ökosystem: Seit 2020 unterstützt Oracle die ECMA-Arbeitsgruppe zur Spezifizierung der Sprache JavaScript durch eine Mitgliedschaft finanziell und hat mit GraalJS eine eigene Implementierung von Ecma-Script auf Basis der GraalVM.
URL dieses Artikels:
https://www.heise.de/-9781727
Links in diesem Artikel:
[1] https://www.heise.de/news/Java-20-erweitert-die-Nebenlaeufigkeit-mit-Scoped-Values-7549078.html
[2] https://www.theregister.com/2023/07/24/oracle_java_license_terms/
[3] https://www.theregister.com/2024/06/20/oracle_java_licence_teams/
[4] https://houseofbrick.com/blog/oracle-java-licensing-risks-2024/
[5] https://www.heise.de/news/Node-js-Entwickler-Ryan-Dahl-bittet-Oracle-Gebt-die-Marke-JavaScript-frei-7254391.html
[6] https://www.heise.de/blog/Java-ohne-Kopfschmerzen-Distributionen-und-Support-jenseits-von-Oracle-9232113.html
[7] https://www.heise.de/news/Java-Amazons-OpenJDK-Variante-Corretto-ist-allgemein-verfuegbar-4295845.html
[8] https://open-elements.com/temurin-support/
[9] https://www.heise.de/news/AdoptOpenJDK-landet-bei-der-Eclipse-Foundation-4789835.html
[10] https://adoptium.net/de/blog/2024/06/external_audit/
[11] mailto:rme@ix.de
Copyright © 2024 Heise Medien
OpenElements startet gemeinsam mit den Maintainern von Apache Maven ein Support&Care-Programm und ruft die Java Community zur Mitarbeit auf.
Open Elements [1] setzt sich zusammen mit Maintainern des Open-Source-Projekts Apache Maven [2] und Experten der Apache Foundation dafür ein, dass das Java-Build-Tool Maven mit nachhaltiger, öffentlicher Förderung langfristig unterstützt wird. Das neue Support & Care for Apache Maven Programm [3] soll die Pflege und Weiterentwicklung dieses zentralen Open-Source-Werkzeugs gewährleisten. Hierzu wird die gesamte Java-Community eingeladen, sich mit Ideen einzubringen und so aktiv die Zukunft von Maven mitzugestalten.
Maven hat sich als der Industriestandard für Build-Tools im Java-Ökosystem etabliert. Mit ca. 75 % aller Java-Projekte, die Maven verwenden [4], und über 100 Millionen Downloads pro Jahr [5] ist es der Standard zum Bauen und Verwalten von Java-Anwendungen. Von kleinen Projekten bis hin zu globalen Softwareunternehmen verlässt sich eine breite Entwicklerbasis auf Maven, um ihre Builds zu konfigurieren und zu automatisieren. Allerdings entwickelt sich die Technologie rund um Java schnell weiter, was regelmäßig neue Versionen und Verbesserungen hervorbringt. Maven muss daher kontinuierlich angepasst werden, um die aktuellen Java-Versionen zu unterstützen. Dies umfasst nicht nur die Implementierung neuer Funktionen, sondern auch das Bereitstellen von Updates, um den Anforderungen an Stabilität und Sicherheit gerecht zu werden.
Zusätzlich gibt es mit dem Erscheinen von Maven 4 zwei Major Versionen (Maven 3 und 4), die in Zukunft von Enterprise Anwendungen benötigt werden, da diese einige Zeit zur Migration auf die neue Java Version benötigen. All dies macht die Entwicklung und das Bugfixing von Maven komplizierter. Hinzu kommt, dass Stand heute kein einziger Entwickler für die Arbeit an Maven bezahlt wird. Selbst der Chair des Projektes bekommt hier nur minimale Spenden über GitHub Sponsoring.
Um Maven als Open-Source-Projekt auch in Zukunft sicher und stabil nutzen zu können, werden Ressourcen benötigt. Dies das Projekt Support & Care for Apache Maven [6] ermöglichen. Die Firma Open Elements, die mit dem klaren Fokus der Förderung von Open Source und Java gegründet wurde, hat sich hier mit verschiedenen Committern, Maintainern sowie Expertinnen und Experten der Maven- beziehungsweise Java-Szene zusammengetan, um gemeinsam öffentliche Gelder für die Weiterentwicklung von Maven zu akquirieren und transparent für die Umsetzung von dringend benötigten Meilensteinen zu verwenden.
Durch Support & Care for Apache Maven wird hierbei etwas ermöglicht, was für einzelne Developer des Maven Projektes bisher nicht realisierbar war: Mit Open Elements kann eine Legal Entity nach außen das Projekt vorantreiben und committet sich dazu, die Einnahmen für das Projekt transparent und ziel- sowie Community-orientiert zu verwalten. Das Vertrauen, das die Maven-Community hierbei Open Elements als transparenten Player im Open Source Bereich entgegenbringt, ist einmalig und ermöglicht dieses Vorhaben überhaupt erst.
Da das Ganze bereits von Anfang an so offen und transparent wie möglich gestaltet werden soll, ist die gesamte Community eingeladen, sich mit Vorschlägen bezüglich benötigter Meilensteine und Features zu beteiligen. Auf der JSail Unconference [7] im Juni werden die finalen Meilensteine definiert, die durch geförderte Ressourcen umgesetzt werden sollen. Bis dahin können alle ihre Vorschläge in den Diskussionen des GItHub-Repository zu Support & Care for Apache Maven [8] einreichen. Auf dieser Basis werden dann auf der JSail in einem moderierten Meeting die finalen Meilensteine und die Roadmap definiert. Auch dieses Event ist öffentlich.
Sobald die Roadmap finalisiert ist, kann die Gruppe hinter Support & Care for Apache Maven mit der konkreten Beauftragung von geförderten Finanzen beginnen. Der Status wird hierbei jederzeit transparent im GitHub Repository des Projekts [9] geteilt. Ziel ist es, das Tool Maven zukunftsbereit und sicher zu gestalten und zu zeigen, dass solche Vorhaben transparent in der Community umsetzbar sind. Hierbei werden die Workflows und Anträge selbstverständlich nach der Beantragung öffentlich bereitgestellt, um auch anderen Communities zu helfen diesen Schritt zu gehen.
Das Projekt kann nur mit und durch die Community realisiert werden. Daher laden wir hier noch einmal herzlich dazu ein, sich bei der Diskussion um benötigte Features unter https://github.com/OpenElements/maven-support-care/discussions [10] zu beteiligen.
URL dieses Artikels:
https://www.heise.de/-9718336
Links in diesem Artikel:
[1] https://open-elements.com/
[2] https://maven.apache.org/
[3] https://open-elements.com/support-care-maven/
[4] https://bit.ly/3Wazfga
[5] https://bit.ly/449qVz0
[6] https://open-elements.com/support-care-maven/
[7] https://jsail.ijug.eu/
[8] https://github.com/OpenElements/maven-support-care
[9] https://github.com/OpenElements/maven-support-care
[10] https://github.com/OpenElements/maven-support-care/discussions
[11] mailto:rme@ix.de
Copyright © 2024 Heise Medien
(Bild: peampath2812/Shutterstock.com)
Die JavaLand-Konferenz steht kurz bevor, wir haben mit einigen Community-Vertretern über die Konferenz gesprochen.
Zum runden JavaLand-Jubiläum haben wir mit Gregor Trefs, Sandra Ahlgrimm, Thomas Much und Gerd Aschemann gesprochen. Sie berichten über ihre bisherigen Erfahrungen und warum sie auch in diesem Jahr wieder dabei sein werden.
Javaland 2024 - Warum bist du dabei?
Gregor Trefs: Meinen ersten Vortrag auf einer Konferenz habe ich tatsächlich auf dem JavaLand [1] gehalten. Und über mehrere Jahre hinweg habe ich zusammen mit Falk einen Workshop durchgeführt, der Java-Programmierern die Grundlagen der funktionalen Programmierung näherbringen sollte. Die Offenheit und positive Atmosphäre der Veranstaltung haben mich immer beeindruckt. Die lebhaften Diskussionen und vielfältigen Perspektiven empfinde ich als äußerst bereichernd. Deshalb habe ich in diesem Jahr eine Deep Dive Session zum Thema "Stateful Property Based Testing und Refactoring" eingereicht. Über einfache Beispiele hinaus zeige ich, wie Property Based Testing in zustandsbehafteten Umgebungen eingesetzt werden kann und wie man jqwik geschickt für Refactoring-Zwecke nutzt.
Sandra Ahlgrimm: Mit die wichtigste Java-Community-Konferenz wollte ich nicht verpassen.
Thomas Much: JavaLand macht einfach Spaß! Die lockere Atmosphäre, die abwechslungsreichen Formate, die Speaker und Teilnehmer aus dem In- und Ausland – das ist jedes Jahr wieder schön zu erleben, und zwar sowohl als Teilnehmer als auch als Speaker. Die Lockerheit und Vielfalt trägt vielleicht auch dazu bei, dass man nicht nur alte Bekannte gerne wieder trifft, sondern dass man auch regelmäßig mit neuen Menschen in den Austausch kommt.
Außerdem findet das JavaLand immer früh im Jahr statt, nach der Winter-Verschnaufpause, wenn der persönliche Akku wieder aufgeladen ist und die neuen Ideen sprudeln. Mit der Verschiebung in diesem Jahr ist das gerade noch so im Zeitrahmen.
Gerd Aschemann: JavaLand ist für mich immer einer der Höhepunkt des Konferenzjahres. Ich freue mich neben spannenden Vorträgen vor allem auch auf die abwechslungsreichen Community-Events. Ich genieße es, mit Gleichgesinnten Neues zu entdecken und mich in entspannter Atmosphäre austauschen zu können.
Dieses Jahr feiert das Javaland sein 10-jähriges Bestehen. Du bist ja jetzt schon seit einigen Jahren quasi Stammgast. Wie hat sich das JavaLand in den 10 Jahren entwickelt?
Gregor Trefs: Seit meinem ersten Besuch im Jahr 2016 hat sich das JavaLand wirklich gut entwickelt. Die Anzahl der Besucher ist gestiegen, es gibt mehr Attraktionen und Highlights im Rahmenprogramm. Die Möglichkeit, Vorträge online zu verfolgen, macht die Teilnahme flexibler. Es ist schön zu sehen, wie die Konferenz wächst und sich weiterentwickelt.
Sandra Ahlgrimm: Meine erste JavaLand-Konferenz musste noch als CyberLand abgehalten werden. Nun habe ich sie bereits im Phantasialand erlebt und bin gespannt, was der neue Standort bereithält. Thematisch war die JavaLand-Konferenz schon immer topaktuell. Daher freue ich mich auch dieses Jahr wieder auf spannende „Aimpulse“.
Thomas Much: Ich bin seit 2016 dabei, die ersten beiden Jahre habe ich also (leider!) verpasst. Größer geworden ist es auf jeden Fall! Gleich geblieben ist die Quirligkeit; man spürt förmlich die Energie auf dem Konferenzgelände. Und damit diese Energie erhalten bleibt, muss sich die Konferenz in vielen kleinen, vielleicht gar nicht so auffälligen Dingen weiterentwickelt haben.
Eine Entwicklung möchte ich dann aber doch hervorheben: Das Newcomer-Programm, bei dem erstmaligen Konferenz-Speakern eine Bühne geboten wird, damit sie Erfahrung sammeln können. Das sorgt für Bodenhaftung bei der Konferenz, bietet den Zuhörern Abwechslung (die Newcomer-Vorträge waren in den letzten Jahren absolut sehenswert!) – und nebenbei zieht sich das JavaLand dadurch die nächste Generation Top-Speaker heran.
Besonders freut mich, dass ich dieses Jahr meinem Kollegen Karl als Newcomer-Mentor zur Seite stehen darf. Karl bringt Bühnenerfahrung als Musiker mit, das merkt man bei den Vorbereitungen. Nun zu erleben, wie akribisch er sich auf seinen ersten Konferenzvortrag vorbereitet, lässt jedem Mentor das Herz aufgehen (@Karl: No pressure! 😉)
Gerd Aschemann: Die JavaLand-Konferenz war schon von Anfang an auf einem hohen Niveau, hat aber auch immer wieder Neues gewagt, manches hat funktioniert, anderes auch mal nicht. Es ist wie im realen Leben der Softwareentwicklung: JavaLand stößt immer wieder in unbekannte Regionen des kollaborativen Austauschs vor. Besonders freue ich mich, dass letztes Jahr unsere “Unkonferenz in der Konferenz” so besonders gut ankam, dass alle Beteiligten quasi von Tobias und mir verlangt haben, dass wir das wiederholen.
Das JavaLand hat dieses Jahr ja eine neue Location. Wie sind hier deine Erwartungen?
Gregor Trefs: Ich bin neugierig darauf, wie JavaLand am Nürburgring ablaufen wird. Ich kann mir gut vorstellen, dass die Wege zu den verschiedenen Vortragsorten jetzt etwas kürzer ausfallen werden im Vergleich zum Phantasialand, wo man am Ende des Tages oft genug seine 10.000 Schritte erreicht hatte. In Bezug auf Konferenzen habe ich immer die Erwartung, etwas Neues zu lernen, selbst wenn es nur eine Kleinigkeit ist. Außerdem war ich bisher noch nie am Nürburgring und bin wirklich gespannt darauf, die Rennstrecke zu erleben.
Sandra Ahlgrimm: Es wird schwierig sein, mit dem Phantasialand mitzuhalten - aber unmöglich ist es nicht!
Thomas Much: Ich hoffe, dass auch die neue Location am Nürburgring einen kreativen Rahmen zum Lernen und Netzwerken bietet – gerne wieder mit einer Mischung von drinnen und draußen, von großen Vortragssälen, wuseligen Plätzen und ruhigen Rückzugsmöglichkeiten. Und wenn am Abend wieder ein nettes Get-together mit guter Musik geboten wird, habe ich da auch nichts gegen.
Die Anfahrt ist allerdings für einen ÖPNV- und Bahnfahrer wie mich in diesem Jahr eine besondere Herausforderung, zumindest fühlt sich das ein wenig so an. Ich habe aber volles Vertrauen in das Orga-Team, dass das mit den Shuttle-Bussen hin und zurück gut klappen wird (und natürlich habe ich meine Shuttle-Tickets schon gekauft).
Alles in allem: Ich erwarte nichts weniger, als dass es einfach wieder richtig gut wird.
Gerd Aschemann: Es ist natürlich ein wenig schade, dass wir hier das gewohnte Umfeld mit seinen Attraktionen, Fahrgeschäften und Plätzen zum Austausch (Cafés, Hackergarten, …) verlassen. Da wir im Vorfeld Räume für unsere eigene Community-Veranstaltung gesucht haben, konnte ich mir aber einen sehr guten Überblick über die Location verschaffen, die viele neue Optionen bietet. Ich freue mich, dass die JavaLand auch hier offen ist.
Das JavaLand versucht sich, als Communty-Konferenz ja immer wieder von anderen Konferenzen abzuheben. Was fällt dir in diesem Zusammenhang besonders auf?
Gregor Trefs: Das JavaLand bemüht sich immer sehr um Feedback, nimmt Kritik an, probiert sich stetig zu verbessern und experimentiert. Ein Jahr blieb in meiner Erinnerung haften, als hinter dem Karussell ein eigens für die Community konzipiertes Zelt aufgebaut wurde. Aufgrund der doch kühlen Märztemperaturen wurde es, im nächsten Jahr, wieder entfernt. Dennoch empfand ich es als bemerkenswert, dass dieses Experiment eingegangen wurde, um aus den gewohnten Mustern auszubrechen.
In den iJUG-Versammlungen wird transparent über bestehende Herausforderungen berichtet und welche Unterstützung benötigt wird. Die engagierte Betreuung der User Groups durch das JavaLand beeindruckt mich besonders. Es gibt das JUG Café, wo man mit verschiedenen Java User Groups in Kontakt kommen kann. Nicht zu vergessen ist, dass der gesamte Stream von der Community gestaltet wird. So eine Beteiligung der Community bietet meines Erachtens keine andere Konferenz.
Sandra Ahlgrimm: Die Wahl der Location ist außergewöhnlich. Leider ist der Zeitraum dieses Jahr etwas ungünstig gewählt, da sie mit einer großen anderen Java Community-Konferenz zusammenfällt (Anmerkung der Redaktion: Das ist dem Weggang aus dem Phantasialand geschuldet).
Thomas Much: Es gibt Community-Events! Und zwar, ohne dass es nur "Open Space" oder andere Formate sind, bei denen sich alle – aber eher spontan – einbringen können. Sondern fest eingeplante, vorbereitete Events, bei denen in kleineren Runden oft sehr spezielle Themen diskutiert und ausprobiert werden. Und obwohl klar ist, dass diese Events keine Massen anziehen, bleiben sie seit Jahren im Programm und tragen auch dadurch zur Vielfalt vom JavaLand bei.
Gerd Aschemann: Die Community bedeutet für mich, dass Leute mit unterschiedlichsten Erfahrungen aufeinandertreffen und zu einem Austausch kommen. Die JavaLand-Konferenz hat von ihrem Aufbau und den abwechslungsreichen Veranstaltungsformen her immer schon diesen Austausch besonders gefördert.
Vielen Dank fürs Beantworten der Fragen. Wir freuen uns auf das Wiedersehen bei der JavaLand-Konferenz vom 09. bis 11. April 2024 [2] erstmals am Nürburgring.
URL dieses Artikels:
https://www.heise.de/-9621993
Links in diesem Artikel:
[1] https://www.javaland.eu/de/home/
[2] https://www.javaland.eu/de/home/
[3] mailto:rme@ix.de
Copyright © 2024 Heise Medien
(Bild: Open Elements)
Für Java gibt es eine Fülle an verschiedenen Logging-Bibliotheken und Möglichkeiten, Log-Nachrichten auszugeben. Aber welche davon sind wirklich performant?
In den vorherigen Posts zum Thema Java Logging (Best Practices [1], Logging Facades [2]) habe ich bereits erwähnt, dass es eine Fülle an Java Libraries zum Thema Logging gibt. Nachdem wir im letzten Post geklärt haben, wie man mit einer Facade verschiedene Logger vereinen kann, wollen wir uns nun die Performance von Logging-Bibliotheken anschauen.
Um kleine Teile einer Java-Anwendung oder -Bibliothek mittels eines Benchmarks zu überprüfen, gibt es in Java das Tool Java Microbenchmark Harness (JMH) [3], das vom OpenJDK bereitgestellt wird, um Performance-Benchmarks durchzuführen. Es führt ähnlich wie bei Unit-Tests kleine Teile der Anwendung (Micro-Benchmarks) aus und analysiert sie. Hierbei kann man unter anderem einstellen, ob der Code zuvor mehrfach für ein paar Sekunden ohne Messung durchlaufen soll, um die JVM und JIT "warmzulaufen".
Diese und andere Parameter lassen sich bei JMH ähnlich wie bei JUnit einfach durch Annotations definieren. Ein simples Beispiel für einen Benchmark sieht folgendermaßen aus:
@Benchmark
@BenchmarkMode(Mode.Throughput)
@Warmup(iterations = 4, time = 4)
@Measurement(iterations = 4, time = 4)
public void runSingleSimpleLog() {
logger.log("Hello World");
}
Das Beispiel führt vier Durchläufe zum Aufwärmen durch, gefolgt von vier Messdurchläufen. Jeder Durchlauf dauert vier Sekunden, und das Messergebnis zeigt an, wie viele Operationen pro Sekunde durchgeführt werden konnten. Konkret bedeutet das, wie oft "Hello World" geloggt werden konnte. Das Ganze bekommt man nach dem Durchlauf tabellarisch in der Kommandozeile ausgegeben, kann es aber auch beispielsweise als JSON- oder CSV-Datei speichern.
Mithilfe von JMH habe ich einen Open-Source-Benchmark für Logging-Frameworks erstellt, das bei GitHub einsehbar ist [4]. Er überprüft aktuell folgende Logging-Bibliotheken beziehungsweise Set-ups auf ihre Performance:
Für jede dieser Konstellation gibt es verschiedene Benchmarks, die die Performance vom Erstellen des Logger über das Loggen einer einfachen "Hello World"-Nachricht bis hin zu komplexen Logging-Aufrufen (Placeholder in Message, Marker, MDC Nutzung, etc.) messen.
Die Messungen zeigen, dass Logging-Frameworks generell sehr performant sind. Auf der anderen Seite führten sie aber auch ein paar Erkenntnisse zutage, die sicherlich nicht jedem direkt klar sind.
Im Folgenden findet sich eine Übersicht von Messergebnissen beim einfachen Loggen einer "Hello World" Nachricht:
Ein erstes Ergebnis der Messungen ist, dass ein Logging auf die Konsole immer deutlich langsamer ist als ein Logging ins Dateisystem. Während man beim Logging in eine Datei 200.000 bis 300.000 Aufrufe des Loggers pro Sekunde erreichen kann, sind es bei einer Ausgabe auf die Konsolen immer deutlich unter 100.000 Operationen die Sekunde gewesen. Da alle Logging-Libraries hier mit System.out bzw. System.err arbeiten, macht es auch kaum einen Unterschied in der Performance, welche Bibliothek man nutzt. Hier wird es in Zukunft spannend zu schauen, ob man durch Tricks oder Umbauten eine bessere Performance hinbekommen kann.
Einen weiteren großen Unterschied sieht man, wenn man die Messwerte von synchronen bzw. asynchronen Logging in eine Datei betrachtet. Hier wird sofort deutlich, dass asynchrones Logging deutlich schneller ist. Die folgenden Tabellen zeigen die Messwerte von asynchronen Logging im Vergleich zu synchronen Logging:
Die klar erkennbar höherer Performance liegt daran, dass die Schreiboperation der asynchronen Logger nicht blockiert. Die Logger Log4J2 und Chronicle Logger nutzen zwar intern unterschiedliche Bibliotheken intern, basieren aber beide auf einer "lock-free inter-thread communication library". Während bei Log4J hierbei LMAX Disruptor [5] als Bibliothek hinzugefügt werden muss, die intern über Ringbuffer das asynchrone Logging ermöglicht, basiert der Chronicle Logger direkt auf der Chronicle Queue Bibliothek [6].
Konkrete Beschreibung der intern genutzten Libraries und wie diese eine asynchrone Kommunikation beziehungsweise das Schreiben ins Dateisystem ermöglichen, lässt sich der Dokumentation entnehmen.
Wenn man die Performance von Log4J2 und Chronicle Logger vergleicht, kann man sehen, dass der Chronicle Logger noch einmal deutlich schneller ist. Dieser Performance-Vorteil kommt aber auch mit einem Nachteil, dem man sich bewusst sein muss: Während Log4J2 auch im asynchronen Modus weiterhin zeilenweise ein für den Menschen einfach lesbares Logging im Dateisystem erzeugt, schreibt der Chronicle Logger alle Nachrichten in einem Binärformat. Hier wird zum Lesen bzw. Parsen dann ein Tooling benötigt, das der Logger aber mitliefert. Darüber hinaus ist die Varianz der Testergebnisse des Chronicle Logger deutlich höher. Als Grund vermute ich, dass die genutzt Chronicle Queue die binären Daten zum Schreiben des Logging intern verwaltet und deren Größen immer dynamisch anpasst. Dies muss allerdings noch weiter untersucht werden. Die folgende Tabelle zeigt einmal eine Übersicht der Varianz:
Wie man sehen kann, ist nicht nur die Wahl einer Logging Bibliothek, sondern auch deren Konfiguration extrem wichtig für die Performance. Während das Logging auf die Konsole während der Entwicklung sicherlich sehr angenehm ist, kann man sich beispielsweise überlegen, ob die Nutzung des Konsolen-Logging im Live-Betrieb wirklich immer erforderlich ist. Auch zeigt sich, dass eine Nutzung von asynchronen Loggern sinnvoll sein kann, wenn die Performance des Systems wirklich kritisch ist. Das kommt aber natürlich mit einer höheren Komplexität und zusätzlichen transitiven Abhängigkeiten einher. Letztlich muss also jedes Projekt weiterhin selbst für sich entscheiden, welcher Logger am sinnvollsten ist. Durch die hier genannten Zahlen hat man aber nun eine weitere Basis, um das festzulegen.
URL dieses Artikels:
https://www.heise.de/-9278737
Links in diesem Artikel:
[1] https://www.heise.de/blog/Best-Practices-und-Anti-Pattern-beim-Logging-in-Java-und-anderen-Sprachen-7336005.html
[2] https://www.heise.de/blog/Logging-Facades-fuer-Java-7355974.html
[3] https://github.com/openjdk/jmh
[4] https://github.com/OpenElements/java-logger-benchmark
[5] https://github.com/LMAX-Exchange/disruptor
[6] https://github.com/OpenHFT/Chronicle-Queue
[7] mailto:rme@ix.de
Copyright © 2024 Heise Medien
Das Java Module System ist in der Entwicklung von Anwendungen und Bibliotheken noch immer eine selten genutzte Funktion. Dabei ist der Einstieg oft leicht.
In den letzten Jahren hat man immer wieder viele unterschiedliche Meinungen zum Java-Modulsystem gehört. Während viele Entwicklerinnen und Entwickler der standardisierten Möglichkeit zur Definition von Modulen positiv entgegenstehen, gibt es viele kritische Meinungen, die der Definition beispielsweise fehlende Features wie die Unterstützung von Versionen ankreiden. Diese Diskussion möchte ich hier allerdings überhaupt nicht aufmachen. Ich selber sehe viele Vorteile im Modulsystem und kann verstehen, dass vor allem Framework und Bibliotheksentwickler das Ganze nutzen (wollen).
Ein großer Nachteil ist hier allerdings, dass eine (transitive) Abhängigkeit, die in keiner Weise auf das Java Modulsystem angepasst ist, möglicherweise nicht zu den Definitionen und Einschränkungen des Modulsystems passt und somit nicht zum Modul-Path hinzugefügt werden kann. Das Java-Modulsystem erstellt automatisch ein Modul für jedes JAR, das es auf dem Modul Path findet. Hierbei kann es zu einigen Problemen kommen, die man allerdings oft durch kleine Anpassungen in einer Bibliothek beheben kann.
Diese Probleme möchte ich in mehreren Posts einmal genauer betrachten und mögliche Lösungen aufzeigen. Dieser Beitrag geht auf die Nutzung und Definition von automatischen Modulen einmal genauer ein.
Eine wichtige Definition des Modulsystems ist, dass jedes Modul einen eindeutigen Namen benötigt. Hierbei wird zwischen explizit deklarierten Modulen, die über eine module-info.java verfügen, und automatischen Modulen, die implizit deklariert werden, unterschieden. Weitere Infos lassen sich der JavaSE Spec [1] entnehmen. Wenn man in seinem Projekt nicht die Vorteile des Modulsystems durch die Nutzung einer module-info.java nutzen möchte, reicht es völlig aus, wenn man die eigene Bibliothek als automatisches Modul definiert.
Die einzige Voraussetzung hierfür ist, dass das Modul über einen eindeutigen Namen verfügt. Zwar kann Java für JARs auf dem Module Path zur Not sogar einen Namen aus dem Namen des JAR extrahieren, was aber ganz klar nicht empfohlen ist. Vor allem, da die Definition eines Namens für ein automatisches Modul wirklich sehr einfach ist. Es muss lediglich die Automatic-Module-Name Property in der MANIFEST.MF des JARs definiert werden. Wenn Maven oder Gradle als Buildtool genutzt werden, kann man dies über ein Plug-in sogar voll automatisiert erstellen.
Wie man im folgenden Beispiel sehen kann, muss bei einem Maven Build nur das maven-jar-plugin entsprechend konfiguriert werden:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>com.example.lib</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
In Gradle lässt sich das Ganze einfach durch Nutzung des Java-Library-Plug-ins umsetzen, das Bestandteil jedes Java Builds sein sollte. Eine ausführliche Dokumentation zum Einsatz in Gradle kann man hier [2] finden, während der folgende Code eine einfache Einbindung in ein Projekt zeigt:
tasks.jar {
manifest {
attributes("Automatic-Module-Name" to "com.example.lib")
}
}
Da die Änderungen wirklich sehr einfach sind, eignen sie sich auch hervorragend, um das Ganze für Open Source Libraries als Pull Request anzubieten. In einem Beispiel [3] habe ich einen PR zur Definition eines Automatic-Module-Name zu einer Open Source-Java-Bibliothek hinzugefügt. Vielleicht liest ja eine oder ein Open Source Developer mit und erstellt für eine solche Umstellung der eigenen Bibliotheken ein „Good First Issue“, das beispielsweise zum Hacktoberfest [4] von Neulingen umgesetzt werden kann.
URL dieses Artikels:
https://www.heise.de/-7434695
Links in diesem Artikel:
[1] https://docs.oracle.com/javase/specs/jls/se16/html/jls-7.html#jls-7.7.1
[2] https://docs.gradle.org/current/userguide/java_library_plugin.html#sec:java_library_modular_auto
[3] https://github.com/offbynull/portmapper/pull/48
[4] https://hacktoberfest.com
[5] https://heise-academy.de/schulungen/virtual-threads?wt_mc=intern.academy.ix.ws_virtualthreads.newsticker.link.link
[6] mailto:rme@ix.de
Copyright © 2024 Heise Medien
Dass die JavaLand 2024 nicht mehr im Phantasialand stattfindet, eröffnet der Community-Konferenz neue Möglichkeiten.
Vor kurzem ist die Bombe geplatzt: Die JavaLand 2024 [1] kann doch nicht wie geplant im Februar am gewohnten Ort stattfinden. Stattdessen wird sie das erste Mal seit ihrem Bestehen an eine neue Location umziehen. Im April wird sich die Java-Community nächstes Jahr nicht mehr im Freizeitpark, sondern am Nürburgring treffen. Wir sind uns sicher, dass diese Neuigkeiten bei vielen Community-Mitgliedern Fragen aufwerfen, allen voran: Warum geht ihr von dieser coolen Location weg? Wir möchten diesen Blogbeitrag nutzen, um unsere persönliche Sichtweise darzustellen, auch wenn die offizielle Pressemitteilung schon einige Fragen beantwortet [2]. Uns ist die Community wichtig und hier können wir etwas konkreter werden. Vor allem möchten wir Gerüchten vorbeugen.
Wie viele aus der Community fanden auch wir das Phantasialand als Location einen Lichtblick im Einheitsgrau der Hotel-Lobbys, Kongresszentren und Kinosäle (wobei die schon auch cool sind). Aber die Location war nicht der einzige Punkt, denn die JavaLand hat dank uns allen (Sprechern, Besuchern, Java User Groups, Aussteller ...) noch einiges mehr zu bieten und hebt sich positiv aus der Konferenzlandschaft ab. Diesen ganz eigenen Spirit empfinden wir bis heute als einmalig und wollen ihn als Mitglieder der Konferenzleitung auch in Zukunft sichern und weiter ausbauen.
Aber die Hürden, die JavaLand im Phantasialand durchzuführen, waren zuletzt zu hoch geworden. Es hatte sich bereits in den vergangenen Jahren gezeigt, dass das Event-Management des Phantasialand nicht in der Lage ist, eine JavaLand nach den Wünschen unserer Community durchzuführen. Leider haben die vielen Bemühungen nicht ausgereicht, um die problematischen Punkte zu klären. Das Phantasialand-Management hat nicht flexibler agiert. Vielmehr wurde die Situation für uns in der Planung und Durchführung der Konferenz jedes Jahr schwieriger. Nächstes Jahr hätten diese Punkte auch das erste Mal alle Besucher direkt betroffen. Wir hätten eine JavaLand im kühlen Februar ohne Nutzung der Fahrgeschäfte gehabt. Dazu kam, dass die Konferenzleitung auch die Preiserhöhungen (inklusive der Hotelpreise) nicht mehr sinnvoll abfangen konnte, sodass dem Rückgang beim Spirit eine deutliche Erhöhung der Kosten pro Besucher gegenübergestanden hätte. Wir möchten hier nicht noch konkreter werden und auch ein Bashing gegenüber dem Phantasialand vermeiden. Allerdings sind wir der Meinung, dass diese offene Begründung nötig ist, um Gerüchte oder Fehlinformationen zu vermeiden. Am Ende unterscheidet sich unsere Java Community zum Glück grundsätzlich von der Klientel, die sich das Phantasialand Event-Management offenbar als Kunden wünscht.
Das Ganze führt uns nun zur aktuellen Situation und der Bekanntmachung der großen Änderungen für die JavaLand 2024. Und das dann auch noch zum 10. Jubiläum. Wird es die gleiche Konferenz sein wie bisher? Ganz bestimmt nicht. Aber gerade wir als agile Entwickler wissen ja, Änderungen gehören zu unserem Alltag. Sie bringen auch immer Fortschritt und ganz neue Möglichkeiten. Aktuell gibt es viele Diskussionen in der Konferenzleitung, wie wir den Kern des JavaLand-Spirit an die neue Location mitnehmen und durch weitere Aspekte sinnvoll ergänzen können. Der Vorteil ist, dass der Nürburgring bereits einiges an Attraktionen zu bieten hat. Denkbar sind Rennen in E-Karts (uns ist auch ein gewisser Grad an Nachhaltigkeit wichtig) und es gibt zum Beispiel auch ein 3D Kino. Außerdem sprudeln bereits die Ideen, wie wir mit Ständen, Foodtrucks, großartigen Abend-Events mit Live-Musik und viele weiteren Attraktionen ein Festival erschaffen und aber auch das Themenpark-Feeling an den Ring holen können.
Hinzu kommt, dass die Location deutlich mehr Möglichkeiten für Community-Aktivitäten bietet. Daher möchten wir euch erneut aufrufen, Ideen für eines der Highlights der JavaLand, das Community-Programm einzureichen. Die Community-Aktivitäten reichen vom direkten Austausch in Diskussionsrunden über kleine Hands-On-Sessions, dem Netzwerken, die Durchführung der JavaLand4Kids bis zu sportlichen Aktivitäten. Das Joggen ist auf jeden Fall wieder dabei, aber vielleicht drehen wir diesmal auch ein paar schnelle Fahrrad-Runden auf dem Nürburgring. Wer mag, kann sich bei der Anreise der JavaLand Fahrrad-Sternenfahrt anschließen, wenn auch diesmal mit ein paar mehr Höhenmetern. Die im vergangenen Jahr erstmals angebotene Unkonferenz wird ebenfalls wieder am Vortag stattfinden. Und im normalen Vortragsprogramm wird es erstmals Deep-Dive-Sessions von fast zwei Stunden geben. All das wird die Black Mamba, die Taron und die anderen coolen Fahrgeschäfte nicht ersetzen können, aber euch wird garantiert nicht langweilig. Und jetzt ist es vielleicht auch leichter, der Chefin oder dem Chef den Besuch bei der JavaLand zu verkaufen.
Wir sind sehr froh über die Neuerungen und sehr gespannt auf die Möglichkeiten, die sich uns bieten werden. Die Planung der JavaLand-Konferenz, die zähen Monate mit den schwierigen Verhandlungen (und den trotzdem nur sehr eingeschränkten Möglichkeiten im Phantasialand) sowie die schwierige Suche nach Alternativen hat uns das erste Mal nicht mehr wirklich Spaß gemacht. Aber diese neue Location bietet nun wieder interessante Optionen, diese ganz besondere Konferenz noch ein Stück besser zu machen. Und hier bitten wir natürlich auch euch, die Java-Community, kreativ zu werden. Macht mit euren Vorschlägen zu den Community-Aktivitäten die JavaLand 2024 wieder zu einem ganz besonderen Erlebnis. Gerade die zehnte JavaLand möchten wir lieber an einem alternativen Ort mit neuen Aktivitäten und Ideen durchführen als unter den leider immer größer werdenden Einschränkungen im Phantasialand.
URL dieses Artikels:
https://www.heise.de/-9322819
Links in diesem Artikel:
[1] https://www.heise.de/news/JavaLand-Konferenz-aendert-den-Termin-und-zieht-zum-Nuerburgring-9317740.html
[2] https://www.javaland.eu/de/home/news/details/javaland-2024-neuer-termin-und-neue-location-call-for-papers-verlaengert/
[3] mailto:rme@ix.de
Copyright © 2023 Heise Medien
(Bild: Natalia Hanin / Shutterstock.com)
Mit dem OpenJDK 21 ist gerade ein Release erschienen, für das Hersteller längeren Support (LTS) anbieten. Diese Version hat aber auch sonst einiges zu bieten.
Mit 15 JEPs (JDK Enhancement Proposals) bringt das OpenJDK 21 so vielen Themen wie lange nicht. Und es hält auch inhaltlich eine Menge interessanter Features für uns Java-Entwickler bereit. Einige Funktionen sind schon länger in Arbeit, darunter das Pattern Matching, die Virtual Threads, die Vector API oder auch die Foreign Function & Memory API. Während beim Pattern Matching und den Virtual Threads Teile finalisiert wurden, bleiben andere Aspekte weiterhin im Preview- oder auch Inkubator-Modus. Für Entwickler besonders spannend sind aber einige ganz neue Themen wie die String Templates, die "Unnamed Classes and Instance Main Methods" (beide zunächst als Preview dabei) und die Sequenced Collections
Beim Pattern Matching geht es darum, bestehende Strukturen mit Mustern abzugleichen, um komplizierte Fallunterscheidungen effizient und wartbar implementieren zu können. Es wird bereits seit einigen Jahren im Rahmen von Project Amber entwickelt. Bis zum letzten Release mit LTS-Support (OpenJDK 17) wurden zunächst nur Basis-Funktionen wie Switch Expressions, Sealed Classes, Records und Pattern Matching for instanceof abgeschlossen. Mit Java 21 kann es nun auch produktiv eingesetzt werden. Mit den Record Patterns und dem Pattern Matching for switch wurden zwei wichtige Bausteine finalisiert. Bei den Record Patterns handelt es sich um einen neuen Pattern Typ, der Records matched und gleichzeitig in ihre Bestandteile zerlegt (dekonstruiert), sodass direkt mit den Komponenten weitergearbeitet werden kann. Und mit Pattern Matching for switch werden alle bisherigen Funktionen zusammengebracht, sodass man in switch-Expressions nun neben den schon immer verfügbaren Constant Patterns auch Type- und Record Patterns inklusive der when-Clauses (früher Guarded Patterns genannt) einsetzen kann. Ganz frisch (in 21 als Preview eingeführt) sind die Unnamed Patterns. Dadurch lassen sich Platzhalter (der Unterstrich _) verwenden, wenn die Pattern Variablen nicht ausgewertet werden sollen. Das macht den Code kompakter, besser lesbar und weniger fehleranfällig (vermeidet toten Code). Dieses Konstrukt lässt sich auch in catch-Blöcken oder bei Lambda-Parametern als sogenannte Unnamed Variables einsetzen.
Da sind sich viele Experten einig und zeigen ihre Begeisterung für eines der wichtigsten Features in der Geschichte von Java, das sich direkt in eine Reihe mit Generics, Lambda-Ausdrücken und dem Plattform-Modul-System einreiht. Die Virtual Threads erlauben eine viel größere Anzahl gleichzeitiger Threads. Sie haben besonders beim Ressourcenverbrauch die Nase vorn gegenüber den klassischen Plattform-Threads. Dadurch können viel mehr (theoretisch Millionen) der virtuellen Threads in einem Prozess gestartet werden, ohne gleich an die Speichergrenzen der VM zu stoßen. Das ermöglicht eine bessere Auslastung der CPU. Die meisten Java Entwickler werden allerdings nicht direkt mit nebenläufiger Programmierung und Virtual Threads in Berührung kommen. Sie profitieren trotzdem, weil Framework-Hersteller (Spring, Quarkus, ...) Virtual Threads unter der Haube einbauen werden. Das ermöglicht gerade bei Webanwendungen eine bessere Auslastung, weil mehr eingehende Requests von Nutzern gleichzeitig verarbeitet werden können. Die Bremse sind ohnehin IO-Zugriffe (z. B. auf die Datenbank). Da die Requests aber sehr günstig zu erzeugen und zu betreiben sind (geringerer Speicherverbrauch) und so viel mehr gleichzeitig verwaltet werden können, lassen sich die vorhandenen Ressourcen besser nutzen.
Im Umfeld der nun abgeschlossenen Virtual Threads gibt es noch zwei, erneut als Preview erschienene Funktionen, die Structured Concurrency und die Scoped Values. Letzteres ist eine bessere Alternative zu den ThreadLocal-Variablen. Und Structured Concurrency ermöglicht die Bearbeitung von mehreren parallelen Teilaufgaben auf eine besonders les- und wartbare Art und Weise.
Einige der vom Funktionsumfang überschaubaren Features sind etwas überraschend im Release von Java 21 aufgetaucht. Besonders spannend sind die String Templates. Sie bringen nicht nur die lang ersehnte String Interpolation in die Java Welt. Die Implementierung ermöglicht in Zukunft sogar das einfache Erstellen eigener Template Prozessoren, die aus Texten mit Platzhaltern zum Beispiel JSON Objekte oder sichere Datenbankabfragen mit PreparedStatements erzeugen können.
Sequenced Collections bringen eine Handvoll neuer Methoden für Collections, deren Elemente in einer wohldefinierten Reihenfolge geordnet sind. Dazu zählen Lese- und Schreibzugriffe (inklusive Entfernen) auf das erste beziehungsweise letzte Element und das Umdrehen der Reihenfolge (reversed()). Dadurch wird das immer noch viel benutzte Collection Framework weiter aufgewertet.
Für Java-Einsteiger wird es in Zukunft auch leichter. Sie müssen zum Erstellen einer ausführbaren Klasse nicht mehr gleich die speziellen Konstrukte wie class, static, public, String[] args usw. verstehen. Mit dem "JEP 445: Unnamed Classes and Instance Main Methods (Preview)" kann man jetzt ausführbare main-Methoden kürzer und prägnanter definieren und sogar auf eine umschließende Klasse verzichten. In Kombination mit dem im JDK 11 veröffentlichten JEP "Launch Single-File Source-Code Programs" lassen sich sehr schlank kleine Java-Anwendungen in einer Textdatei mit einer simplen void main(){}-Methode von der Kommandozeile aufrufen. Und das kommt dann auch erfahrenen Java-Entwicklern zugute.
Die Vector API ist ein Dauerläufer und taucht seit Java 16 regelmäßig in den Releases auf, diesmal als sechster Inkubator (Vorstufe von Preview). Es geht dabei um die Unterstützung der modernen Möglichkeiten von SIMD-Rechnerarchitekturen mit Vektorprozessoren. Single Instruction Multiple Data (SIMD) lässt mehrere Prozessoren gleichzeitig unterschiedliche Daten verarbeiten. Durch die Parallelisierung auf Hardware-Ebene verringert sich beim SIMD-Prinzip der Aufwand für rechenintensive Schleifen.
Auch schon seit einigen Versionen mit an Bord ist die Foreign Function & Memory API, diesmal im 3. Preview. Wer schon sehr lange in der Java-Welt unterwegs ist, wird das Java Native Interface (JNI) kennen. Damit kann nativer C-Code aus Java heraus aufgerufen werden. Der Ansatz ist aber relativ aufwändig und fragil. Die Foreign Function API bietet einen statisch typisierten, rein Java-basierten Zugriff auf nativen Code (C-Bibliotheken). Zusammen mit dem Foreign-Memory Access API kann diese Schnittstelle den bisher fehleranfälligen und langsamen Prozess der Anbindung einer nativen Bibliothek beträchtlich vereinfachen. Mit letzterer bekommen Java-Anwendungen die Möglichkeit, außerhalb des Heaps zusätzlichen Speicher zu allokieren. Ziel der neuen APIs ist es, den Implementierungsaufwand um 90 Prozent zu reduzieren und die Leistung um Faktor 4 bis 5 zu beschleunigen. Beide APIs sind seit dem JDK 14 beziehungsweise 16 im JDK zunächst einzeln und ab 18 als gemeinsamer Inkubator-JEP enthalten. Vermutlich wird sich dieses Feature langsam der Finalisierung nähern.
Bei den Garbage Collectors hat sich auch etwas getan. Der vor wenigen Jahren im OpenJDK 15 eingeführte ZGC (Scalable Low-Latency Garbage Collector) gehört zu einer neuen Generation. Das Ziel ist, große Datenmengen (TB von RAM) mit möglichst kurzen GC-Pausen (kleiner 10 ms) aufzuräumen und so die Anwendung nahezu immer antwortbereit zu halten. Bisher machte der ZGC keine Unterscheidung zwischen frischen und schon länger existierenden Objekten. Die Idee ist, dass Objekte, die bereits einen oder mehrere GC-Läufe überlebt haben, auch in Zukunft wahrscheinlich noch lange weiterleben werden. Diese werden dann in einen extra Bereich (Old Generation) verschoben und müssen so bei den Standard-Läufen nicht mehr verarbeitet werden. Das kann einen Schub bei der Performance einer Anwendung geben.
Es gibt noch einige weitere, für Entwickler nicht so relevante JEPs. Für die vielen Details lohnt auch ein Blick auf die Release Notes [3]. Änderungen am JDK (Java Klassenbibliothek) lassen sich zudem sehr schön über den Java Almanac [4] nachvollziehen. In dieser Übersicht finden sich unter anderem alle Neuerungen zu den String Templates und den Sequenced Collections. In der String-Klasse gab es auch kleine Erweiterungen: Beispielsweise wurde die Methode indexOf(String str, int beginIndex, int endIndex) eingeführt, die in einem bestimmten Bereich nach einem Teil-String sucht. Die Klassen StringBuffer und StringBuilder wurden jeweils um zwei ähnliche Methoden erweitert, die ein Zeichen oder eine Zeichenkette wiederholt mal an das bestehende Objekt anhängen: repeat(CharSequence, int). Die Klasse Character wurde wiederum um eine Vielzahl von Methoden erweitert, die prüfen, ob eine Unicode-Zeichen ein Emoji oder eine Variante davon darstellt. Java geht also auch hier mit der Zeit.
Einen ausführlichen Überblick über das Java-21-Release findet sich im frisch erschienen iX-Artikel [5]. Durch die Finalisierung der Virtual Threads wird Java 21 in ein paar Jahren auf eine Stufe mit Java 5 (Generics), Java 8 (Lambdas, Stream-API) und Java 9 (Plattform Modul System) gestellt werden. Auch wenn sich das Potenzial dieser Idee noch nicht vollständig erfassen lässt, werden die virtuellen Threads die Implementierung von hochskalierbaren Server-Anwendungen in Zukunft stark vereinfachen. Aber Java 21 hält noch viele andere Highlights bereit. Beim Pattern Matching wurden das Kernstück (Pattern Matching for switch) sowie die Record Patterns finalisiert und die Unnamed Patterns als Preview eingeführt. Die String Templates (im Moment noch als Preview) und auch die Sequenced Collections erleichtern Java-Entwicklern das Leben. Das steigert schon jetzt die Vorfreude auf das nächste Release im März 2024.
URL dieses Artikels:
https://www.heise.de/-9309203
Links in diesem Artikel:
[1] https://java.bettercode.eu/
[2] https://java.bettercode.eu/index.php#programm
[3] https://jdk.java.net/21/release-notes
[4] https://javaalmanac.io/jdk/21/apidiff/17/
[5] https://www.heise.de/tests/Java-21-Version-mit-LTS-String-Templates-und-Virtual-Threads-vorgestellt-9302335.html
[6] mailto:rme@ix.de
Copyright © 2023 Heise Medien
Der Community Day für Java Developers bietet am 16. Oktober Expertenvorträgen und Demos, die sich auf Java und Open Source konzentrieren.
Der iJUG e.V. [1] (Interessenverbund der Java User Groups) hat sich mit der Eclipse Foundation [2] zusammengetan, um im Rahmen der EclipseCon am 16. Oktober ein Tagesevent speziell für die (deutschsprachige) Java Community zu gestalten. Hier gibt es einen ganzen Tag voll Java Themen zu einem fairen Preis.
Der Community Day für Java Developers [3] auf der EclipseCon [4] ist ein ganztägiges Programm mit Expertenvorträgen, Demos und anregenden Sessions, die sich auf Java und die Entwicklung von Unternehmensanwendungen unter Verwendung von quelloffenen, herstellerunabhängigen Prozessen und Technologien konzentrieren. Die Open-Source-Projekte Jakarta EE [5], Adoptium [6] und MicroProfile [7] sowie andere von der Eclipse Foundation gehostete Java-Projekte und -Communities werden von weltweit führenden Java-Innovatoren wie Azul [8], Google [9], IBM [10], Microsoft [11], Open Elements [12], Oracle [13], Red Hat [14] und Tomitribe [15] unterstützt.
Mit 14 technischen Sessions, Networking und Verpflegung kostet das eintägige Event weniger als 50 Euro. Das wird durch die Zusammenarbeit zwischen der Eclipse Foundation, dem iJUG e.V. und den Sponsoren der EclipseCon ermöglicht.
Die Veranstaltung ist eine gute Gelegenheit, um herauszufinden, wie andere diese Technologien nutzen, sich mit Expertinnen und Experten aus der Community zu treffen, die wichtigsten Aspekte der Jakarta EE-, Adoptium- und MicroProfile-Technologien besser zu verstehen und Ideen mit innovativen Personen und Unternehmen des Ökosystems zu teilen.
URL dieses Artikels:
https://www.heise.de/-9192048
Links in diesem Artikel:
[1] https://www.ijug.eu/
[2] https://www.eclipse.org/
[3] https://www.eclipsecon.org/2023/java-community-day
[4] https://www.eclipsecon.org/2023
[5] https://jakarta.ee/
[6] https://adoptium.net/
[7] https://microprofile.io/
[8] https://www.azul.com/
[9] https://about.google/
[10] https://www.ibm.com/
[11] https://www.microsoft.com/
[12] https://open-elements.com/
[13] https://www.oracle.com/
[14] https://www.redhat.com/
[15] https://www.tomitribe.com/
[16] mailto:rme@ix.de
Copyright © 2023 Heise Medien
(Bild: Sundry Photography/Shutterstock.com)
Es gibt nicht nur einen Anbieter für Java-Distributionen und Support. Gartner hat in einem Report die Optionen analysiert, und Oracle schneidet nicht gut ab.
Für die meisten Unternehmen gehören sowohl Java als Programmiersprache als auch die JVM als Laufzeitumgebung zur kritischen Infrastruktur, auf der ein großer Teil unserer digitalen Welt aufgebaut ist. Da für die kritische Infrastruktur im Enterprise-Umfeld immer geraten wird, über passende Support-Möglichkeiten zu verfügen, besitzen viele Firmen einen kommerziellen Support-Vertrag für Java. Diese Verträge wurden historisch oft mit Oracle geschlossen, da das Unternehmen lange Zeit der prominenteste Anbieter für Java-Distributionen war. Da sich aber in den letzten Jahren viel in diesem Bereich getan hat, stellt sich die Frage, ob Oracle hier noch immer der beste Partner für den kommerziellen Support von Java ist.
In vielen Bereichen der heutigen Welt ist Diversität ein wichtiges Thema, da hierdurch neue Ansichten, Lösungen und Möglichkeiten entstehen. Auch im Bereich der Java-Laufzeitumgebungen hat sich hier in den letzten Jahren einiges getan. Die Zeit, in der Entwicklerinnen und Entwickler Java prinzipiell von Oracle heruntergeladen haben, da es der Platzhirsch bei Java-Distributionen war, ist lange vorbei. Durch die fortschreitende Beliebtheit von Open Source arbeiten mehr und mehr Firmen am OpenJDK [1] mit, der quelloffenen Implementierung der Java Standard Edition. Da auch die Distributionen von Oracle aus diesen Quellen gebaut werden, kann man somit auch problemlos zu Alternativen greifen. Dazu kommt, dass durch das Java Test Compatibility Kit (TCK) viele der Laufzeitumgebungen auf ihre Kompatibilität zum Standard hin überprüft werden.
Eclipse hat einen Marketplace eröffnet [2], in dem alle TCK und AQAvit verifizierten beziehungsweise lizenzierten Java-Laufzeitumgebungen zum Download angeboten werden. Neben verschiedenen Builds von Firmen wie Microsoft oder Azul tut sich hier vor allem Eclipse Temurin [3] hervor, das als einzige Java Distribution eine herstellerunabhängige Variante ist. Verantwortlich ist die Eclipse-Adoptium-Arbeitsgruppe, der Firmen wie Microsoft [4], Red Hat [5], Google [6] und Open Elements [7] angehören. Mit über 200 Millionen Downloads [8] gibt es auch keine andere Java-Distribution, die aufgrund ihrer Zahlen auch nur ansatzweise an die Verbreitung von Eclipse Temurin herankommt. Dies unterstreicht ein aktueller Gartner-Bericht [9], laut dem 2026 über 80 Prozent aller Java Anwendungen voraussichtlich nicht auf einer Oracle-Distribution laufen werden. Eclipse Temurin macht hier am Ende sicherlich das größte Stück des Kuchens aus.
Neben der Analyse verschiedener Distributionen hat Gartner die verschiedenen Möglichkeiten der kommerziellen Support-Optionen für Java untersucht. Hierbei hat vor allem der Oracle-Support nicht wirklich gut abgeschnitten:
Oracle hat erneut die Lizenzregeln für seine Java-Distributionen geändert. Am 23. Januar 2023 führte das Unternehmen eine neue Lizenzmetrik ein, die SE Universal Subscription [10]. Das kontroverse Preismodell zieht als Basis die Gesamtzahl der Kundenmitarbeiter heran und nicht die Anzahl der Mitarbeiter, die die Software nutzen. Möglicherweise versucht Oracle so, dass Kunden keine anderen Support-Modelle für Java in Erwägung ziehen. Für Kunden führt das in vielen Fällen dazu, dass die Support-Kosten für Java durch die Decke gehen. Laut Gartner entstehen hier für die meisten Organisationen zwei- bis fünfmal so hohe Kosten. Dazu kommt natürlich, dass man durch einen kommerziellen Support bei Oracle nur Support für die Oracle-Distribution erhält und nicht etwa für das immer beliebter werdende Eclipse Temurin. Vielleicht ist daher genau jetzt der richtige Zeitpunkt, sich einmal nach alternativen Angeboten für Java Support umzuschauen.
Natürlich haben Organisationen wie Azul oder auch die Arbeitsgruppe von Eclipse Adoptium auf diese Ereignisse reagiert. Mike Milinkovich, der Executive Director der Eclipse Foundation [11], kommentierte das Ganze wie folgt auf X / Twitter:
(Bild: Twitter / X)
Aber neben diesem Kommentar ließ Adoptium auch Taten sprechen und hat eine Seite für kommerziellen Support für Eclipse Temurin [12] eingerichtet. Auf dieser wird mit Red Hat, IBM und Open Elements gleich durch drei Experten der Branche Support für Eclipse Temurin angeboten. Hervorzuheben ist hierbei für den deutschsprachigen Raum Open Elements, da diese mit ihrem "Support & Care"-Paket [13] nicht nur aktiv Temurin als Open-Source-Projekt fördern, sondern auch Support in deutscher Sprache anbieten.
Wie man sehen kann, ist auch das Angebot an Support-Optionen für die Java Laufzeitumgebung in den letzten Jahren deutlich diverser geworden. Neben dem Angebot von Oracle gibt es nun verschiedene Möglichkeiten, die oft deutlich besser auf die eigenen Anforderungen zugeschnitten sind. Natürlich bedeutet das auch, dass jede Firma über den Tellerrand schauen und Alternativen zum bereits vor Jahren abgeschlossenen Oracle-Support begutachten und bewerten muss. Für Firmen, die bisher über keinen Support-Vertrag verfügen, eignen sich einige der Angebote vielleicht deutlich eher, als direkt mit dem Riesen Oracle einen Vertrag zu schließen. Aber auch das Angebot von Oracle hat seine Berechtigung und wird für einige Firmen das passende sein. Daher will ich hier nicht ein Angebot als Gewinner darstellen, sondern die Vielfalt der Möglichkeiten dank Firmen wie IBM, Red Hat, Azul, Open Elements und natürlich Oracle als Gewinn für die gesamte Java Community aufzeigen.
URL dieses Artikels:
https://www.heise.de/-9232113
Links in diesem Artikel:
[1] https://openjdk.org/
[2] https://adoptium.net/marketplace/
[3] https://adoptium.net/de/
[4] https://www.microsoft.com/openjdk
[5] https://www.redhat.com
[6] https://cloud.google.com/java
[7] https://open-elements.com/
[8] https://dash.adoptium.net/
[9] https://www.gartner.com/en/documents/4540799
[10] https://www.oracle.com/us/corporate/pricing/price-lists/java-se-subscription-pricelist-5028356.pdf
[11] https://www.eclipse.org
[12] https://adoptium.net/temurin/commercial-support/
[13] https://open-elements.com/temurin-support/
[14] mailto:rme@ix.de
Copyright © 2023 Heise Medien
(Bild: Shutterstock)
Das ehemals kostenpflichtige GraalVM Enterprise ist jetzt als Oracle GraalVM frei verfügbar. Die Versionsnummerierung wurde zudem dem OpenJDK angepasst.
GraalVM ist eine in Java implementierte JVM (Java Virtual Machine) und ein JDK (Java Developement Kit) basierend auf der Hotspot-VM und dem OpenJDK. Es unterstützt mit GraalVM Native Image unter anderem die AOT-Kompilierung (Ahead of Time) von Java Anwendungen für schnellere Startzeiten und geringeren Speicherverbrauch zur Laufzeit. Initial bei Sun gestartet wird es nun bei den Oracle Labs parallel zu dem klassischen Java OpenJDK entwickelt und war bisher sowohl in einer Open Source lizenzierten Community Edition als auch einer kommerziellen Enterprise Edition verfügbar.
Die Besonderheiten zum normalen Java JDK sind:
Ende 2022 hat Oracle die GraalVM Community Edition an das OpenJDK-Projekt übergeben [1] und damit die Basis des Projekts als Open Source bereitgestellt. Dabei wurde angekündigt, zukünftig die Versionen und Nummerierungen an die Release-Zyklen des OpenJDK anzugleichen. Die erste produktionsreife Version war GraalVM 19.0 im Mai 2019 [2]. Mit GraalVM 22.3.2 kam im April 2023 das bisher letzte Release nach dem alten Nummerierungsschema.
Nun sind Oracle GraalVM für das JDK 17 und Oracle GraalVM für das JDK 20 erschienen [3]. Diese früher als kommerzielle Oracle GraalVM Enterprise bekannten Versionen stehen ab sofort kostenfrei unter der GraalVM Free Terms and Conditions (GFTC) Lizenz zur Verfügung. Diese Lizenz erlaubt die kostenlose Nutzung für alle Benutzer, auch für den Produktionseinsatz. Die Weiterverbreitung ist erlaubt, wenn sie nicht gegen eine Gebühr erfolgt. Entwickler und Organisationen können Oracle GraalVM jetzt einfach herunterladen, verwenden, weitergeben und weiterverteilen, ohne dass sie eine Lizenzvereinbarung durchklicken müssen. Oracle wird weiterhin die GPL-lizenzierten Versionen der GraalVM Community Edition zu den gleichen Bedingungen wie die Oracle-Builds des OpenJDK anbieten.
Etwas unklar ist im Moment die Frage, ob man die eigene Software, die als GraalVM Native Image gebaut wurde, nach GFTC-Lizenz verkaufen darf. Unser Leser Michael Paus hat uns auf eine Diskussion im GraalVM Slack [4] aufmerksam gemacht (um diesen Beitrag lesen zu können, muss man sich zuvor als Benutzer registrieren [5]). Nach dem aktuellen Stand der Diskussion darf man als GraalVM Native Image gebaute Software in Produktion nur kostenfrei für die interne Nutzung oder als Open Source betreiben. Verlangt man eine Gebühr für die eigene Software, muss man auf eine kommerzielle Lizenz von GraalVM ausweichen. Die Kosten dafür richten sich entweder nach den Prozessorkernen, auf denen das Native Image laufen wird oder es wird ein nicht geringer Pauschalbetrag fällig. Auskünfte dazu holt man sich am besten direkt beim Sales & Tech Team bei Oracle ein.
Kurzer Blick auf das klassische Java OpenJDK: Im September 2021 hatte Oracle angekündigt, dass das Oracle JDK (Oracles Variante des OpenJDK) wieder kostenfrei zur Verfügung steht (unter der Oracle No-Fee Terms and Conditions Lizenz - NFTC). Zuvor hatte Oracle 2018 mit dem JDK 8 und 11 eine kommerzielle Lizenz für die produktive Nutzung des Oracle JDK eingeführt.
Alternativ gab es zwar noch das binär-kompatible Oracle OpenJDK kostenfrei, welches aber immer nur maximal ein halbes Jahr mit Updates und Patches versorgt wurde und somit die Entwickler zu halbjährlichen JDK Versionsupdates gezwungen hätte. Seit dieser Zeit sind viele andere auf dem OpenJDK basierende Distributionen von Amazon, IBM, SAP, Microsoft usw. herausgekommen beziehungsweise haben an Bedeutung gewonnen.
Die bekannteste Variante ist das AdoptOpenJDK (mittlerweile Temurin vom Eclipse Projekt Adoptium [6]), welches durch Oracles Lizenz-Wirrwar zum meistverwendeten JDK wurde. Oracle hat das erkannt und durch die erneute kostenfreie Weitergabe des Oracle JDK versucht, Marktanteile zurückzugewinnen. Diesen Ansatz weiten sie nun auch auf Oracle GraalVM mit der GraalVM Free Terms and Conditions (GFTC)-Lizenz aus.
Analog dem OpenJDK wird es nun ebenfalls Long Term Support Releases (aktuell GraalVM für JDK 17) geben, die bis zu einem vollen Jahr nach der Veröffentlichung des nachfolgenden LTS-Release (GraalVM für JDK 21) kostenlos mit Updates versorgt werden. Releases, die nicht als LTS-Releases gekennzeichnet sind (wie GraalVM für JDK 20), werden so lange mit Aktualisierungen versorgt, bis sie durch das nächste Release abgelöst werden. Entwickler können somit jetzt auch bei GraalVM alle sechs Monate auf die neueste JDK-Version aktualisieren und erhalten so sofort Zugang zu den neuesten Java-Funktionen. Alternativ haben Sie die Möglichkeit, zwischen den LTS-Versionen zu wechseln.
Die neuen Oracle GraalVM-Releases lassen sich dank neuer stabiler Download-URLs jetzt leichter in CI/CD-Build-Pipelines einbinden. Die Download-Artefakte enthalten zudem das Native-Image-Dienstprogramm. Somit ist alles in einem einzigen Paket unter derselben Lizenz verfügbar, was für die Entwicklung mit der GraalVM benötigt wird. Für containerisierte Anwendungen oder Container-basierte Builds werden zudem bald neue GraalVM Container-Images auf der Oracle Container Registry verfügbar sein.
Das GraalVM Projekt hat in den vergangenen Jahren eine Menge Aufmerksamkeit erhalten. Das Ziel ist, Javas Rückstand auf moderne Programmiersprachen wie Go in Bezug auf schnelle Startzeiten und effizientes Speicherverhalten zur Laufzeit zu verkleinern. Java ist zwar weiterhin als stabile Laufzeitumgebung für serverseitige Anwendungen vertreten, verliert aber insbesondere beim Umzug in die Cloud Marktanteile an Go & Co. Mit der GraalVM hat man nun auf der Java Plattform die Wahl und kann mit den bestehenden Programmierkenntnissen beide Welten unterstützen. Die Angleichung der Release-Zyklen und der Versionierung an das OpenJDK lassen uns die neuesten Features sowohl im "normalen" Java als auch bei der GraalVM nutzen.
Die Änderungen an den neuen, im Juni 2023 erschienenen GraalVM-Versionen hat Alina Yurenko in ihrem Blog-Post [7] zusammengefasst.
Die neuen Oracle GraalVM Versionen können von der Java-Download-Seite [8] bezogen werden. Weitere Informationen [9] finden sich in den Installationsanleitungen, der Dokumentation und den Versionshinweisen. In der Oracle Cloud Infrastruktur kann Oracle GraalVM übrigens kostenfrei genutzt werden.
Nach Hinweis eines Lesers wurde der Beitrag um einen Absatz ergänzt, der sich den Unklarheiten bezüglich der Bedingungen zum Verkauf eigener Software widmet, die mit GraalVM Native Image gebaut wurden.
URL dieses Artikels:
https://www.heise.de/-9199872
Links in diesem Artikel:
[1] https://www.heise.de/news/Virtuelle-Maschine-Oracle-uebergibt-GraalVM-Community-Edition-an-OpenJDK-7320608.html
[2] https://www.heise.de/news/GraalVM-19-das-erste-offiziell-produktionsreife-Release-4420777.html
[3] https://blogs.oracle.com/cloud-infrastructure/post/graalvm-free-license
[4] https://t.co/Ga1lgeLr91
[5] https://t.co/JFAWTJ9niQ
[6] https://www.heise.de/news/AdoptOpenJDK-landet-bei-der-Eclipse-Foundation-4789835.html
[7] https://medium.com/graalvm/a-new-graalvm-release-and-new-free-license-4aab483692f5
[8] https://www.oracle.com/java/technologies/downloads/
[9] https://docs.oracle.com/en/graalvm/jdk/20/
[10] mailto:rme@ix.de
Copyright © 2023 Heise Medien
(Bild: Black Jack/Shutterstock.com)
Logging ein wichtiger Teil der Fehleranalyse. Allerdings ist das Zusammenführen unterschiedlicher Logging Libs in Java-Anwendungen immer eine Herausforderung.
Nachdem ich im ersten Post zum Thema Java Logging [1] auf Best Practices und Pitfalls eingegangen bin, möchte ich nun einmal auf die Nutzung von Logging in einem großen Projekt eingehen. In diesem Bereich kommt es oft zu Problemen zwischen verschiedenen Logging Frameworks und eine Zusammenführung des gesamten Anwendung-Logging kann sich mitunter schwer gestalten.
Um die Problematik besser zu verstehen, fange ich mit einem ganz einfachen Beispiel, quasi dem Hello World im Logging, an. Der folgende Code zeigt eine minimale Java-Anwendung, welche einfach eine Nachricht loggt:
public class HelloLogging {
private static final Logger LOG = Logger.getLogger("HelloLogging");
public static void main(final String[] args) {
LOG.info("Hello World");
}
}
Bereits in dieser trivialen Anwendung kann das Logging durch die Features des Logging Frameworks, im Beispiel etwa java.util.Logging (JUL), konfiguriert und in einer Datei oder der Konsole (Shell) ausgegeben werden. Das folgende Diagramm zeigt den Aufbau und die Konfiguration des Logging in einem schematischen Aufbau.
Während der gegebene Aufbau für ein kleines Projekt gut funktioniert, wird es manchmal schon problematisch, sobald die ersten Abhängigkeiten hinzukommen. Stellen wir uns einmal vor, dass wir zwei Abhängigkeiten für unsere Anwendung benötigen: eine Library, um den Zugriff zu einer Datenbank zu gewährleisten und eine weitere Abhängigkeit zu einer Security Library, um unsere Anwendung sicher vor Angriffen zu machen. Da die Entwickler dieser Bibliotheken auch Information über dessen Zustand, Nutzung und Laufzeitfehler ausgeben wollen, nutzen diese ebenfalls Logging. Allerdings wird bei diesen Bibliotheken nicht java.util.Logging, sondern es werden andere Logging Libraries genutzt. Wie man im folgenden Diagramm sehen kann, nehmen wir an, dass Log4J2 [2] und Logback [3] im Einsatz sind.
Nun haben wir das Problem, dass das Logging unserer Anwendung über drei verschiedene Logging-Frameworks geleitet wird. Zwar bieten Log4J und Logback auch genug Möglichkeiten der Konfiguration, aber da die Logging Frameworks sich nicht gegenseitig synchronisieren, wäre es eine ganz dumme Idee, alle Frameworks in die gleiche Datei schreiben zu lassen. Hier kann es passieren, dass mehrere der Frameworks in die gleiche Zeile schreiben und es somit zu einem unleserlichen Haufen zufällig aneinandergereihter Textbausteine oder sogar zu Deadlocks kommen kann. Eine andere Idee ist es, dass jedes Framework in eine eigene Datei loggt, wie es im folgenden Diagramm angedeutet ist.
Dieser Aufbau führt dazu, dass die Loggings völlig unabhängig voneinander agieren und sich nicht in die Quere kommen können. Hierdurch hat man zwar ein sauberes Logging, das aber auf mehrere Dateien verteilt ist, die man manuell oder mithilfe von Tools synchronisieren muss. Dazu kommt, dass man immer alle vorhandenen Loggingsysteme konfigurieren muss, wenn man beispielsweise einmal ein höheres Logging-Level zur Analyse der Anwendung aktivieren möchte. Erschwerend kommt hinzu, dass man in einem echten Projekt mehr als nur zwei Abhängigkeiten hat uns es somit zu noch deutlich mehr Logging-Frameworks kommen kann, die im Einsatz sind.
Logging Facades schaffen hier Abhilfe. Durch eine Facade kann man den Code von einer konkreten Implementierung trennen. Die Simple Logging Facade for Java [4] (SLF4J) hat sich hier ganz klar als Standard durchgesetzt. SLF4J bietet eine Logging-API, die als einzelne Abhängigkeit ohne transitiven Abhängigkeiten daher kommt und problemlos in so ziemlich jedes System eingebunden werden kann. Die API kann in diesem Fall genutzt werden, um konkrete Log-Aufrufe im Code zu genieren. Der folgende Code zeigt ein „Hello World“ Logging Beispiel:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HelloLogging {
private static final Logger logger =
LoggerFactory.getLogger(HelloLogging.class);
public static void main(String[] args) {
logger.info("Hello World!");
}
}
Betrachtet man rein diesen Code kann man sich fragen, welche Vorteile SLF4J gegenüber dem klassischen Java-Logging bringen soll. Einer der wichtigsten Punkte ist, dass es sich bei org.slf4j.Logger um ein Interface handelt. Das Modul slf4j-api, das die SLF4J-Api und somit das genannte Interface enthält, liefert keine Implementierung des Interfaces. Das gesamte Modul definiert lediglich die öffentliche API api von SLF4J, die Logging Facade.
Um sie zu nutzen, müssen wir eine Implementierung bereitstellen. Hierfür muss ein sogenanntes Binding als Abhängigkeit hinzugefügt werden, das eine Implementierung der Logging Facade bereitstellt. In der Regel leitet ein solches Binding die Logging-Events an ein konkretes Logging-Framework weiter. Möchte man beispielsweise Apache Commons Logging als konkrete Logging-Implementierung nutzen, muss man nur das slf4j-jcl-VERSION.jar Modul zum Classpath hinzufügen. Solche Bindings werden nicht zur Compiletime benötigt und können daher in Maven per Runtime-Scope bzw. in Gradle als „RuntimeOnly“-Abhängigkeit angegeben werden. Da SLF4J intern das Java-SPI nutzt, muss keinerlei Code angepasst werden, um die konkrete Logging-Implementierung zu verwenden. Dieses Feature können wir nun für unsere Beispielanwendung nutzen:
Im Diagramm wird Log4J2 als Logging-Implementierung genutzt, und durch das Hinzufügen eines passenden Bindings werden alle Log-Nachrichten, die über den org.slf4j.Logger-Logger erstellt werden, automatisch an Log4J2 weitergereicht. Da in diesem Beispiel unsere „Database lib“ Abhängigkeit offenbar auch Log4J2 nutzt, werden so direkt die Nachrichten von verschiedenen internen und externen Modulen über Log4J2 abgehandelt. Neben den Bindings zu speziellen Logging Implementierung bietet SLF4J auch noch die Library slf4j-simple welche eine minimale Implementierung von SLF4J bietet und Nachrichten auf der Konsole (System.error) ausgibt.
Allerdings gibt es im Beispiel auch noch ein Problem: Die genutzte „Security lib“ benutzt Logback als Logger und dessen Nachrichten landen daher weiterhin in einer anderen Ausgabe. Für solche Fälle können sogenannte Adapter für SLF4J genutzt werden. Diese ermöglichen, dass Log-Nachrichten, die direkt zu einer Logging-API geschickt werden, an SLF4J weitergeleitet werden. Hierbei gibt es je nach Logging Framework völlig unterschiedliche Implementierungsansätze für solche Adapter. Während SLF4J einige solcher Adapter anbietet, werden ie auch teils von Logging-Frameworks direkt geliefert. Für Log4J2 muss beispielsweise folgende Abhängigkeit hinzugefügt werden, wenn man Nachrichten von Log4J2 an SLF4J weiterleiten möchte:
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
Durch das Hinzufügen dieser Abhängigkeit, die man am besten nur zur Runtime zum Classpath hinzufügt, entsteht ein Verlauf des Logging wie in der folgenden Grafik :
SLF4J bietet für verschiedene Logging-Libraries eine gute Übersicht bezüglich der Integration durch Bindings und Adapter auf ihrer Webseite [5].
Wenn wir uns basierend auf den Erkenntnissen nun unsere Beispielanwendung anschauen, kann durch das Hinzufügen eines Adapters für Logback unser Ziel erreicht werden. Wie im folgenden Diagramm gezeigt, werden alle Log-Nachrichten des gesamten Systems über Log4J2 geleitet und wir haben somit den Vorteil, dass wir nur eine zentrale Stelle dokumentieren müssen.
URL dieses Artikels:
https://www.heise.de/-7355974
Links in diesem Artikel:
[1] https://www.heise.de/blog/Best-Practices-und-Anti-Pattern-beim-Logging-in-Java-und-anderen-Sprachen-7336005.html
[2] https://logging.apache.org/log4j/2.x/
[3] https://github.com/qos-ch/logback
[4] https://www.slf4j.org
[5] https://www.slf4j.org/legacy.html
[6] mailto:rme@ix.de
Copyright © 2023 Heise Medien
(Bild: Shutterstock)
Mit Java kann man Anwendung mittlerweile gut modularisieren, muss aber auch Abhängigkeiten beachten. Wenn diese keine Java-Module sind, wird es spannend.
In einem vorherigen Post habe ich über eine minimale Unterstützung für das Java Modulsystem (Java Platform Module System, JPMS) geschrieben und wie man helfen kann, sie zu erreichen. Nun kann es aber immer wieder passieren, dass Bibliotheken das Java-Modulsystem nicht unterstützen und es auch nicht absehbar ist, dass diese in Zukunft wenigstens als „Automatische Module“ verfügbar sein werden.
Wenn man seinen eigenen Code auf das JPMS umstellen will und von solchen Bibliotheken abhängig ist, muss man teilweise in die Trickkiste greifen. In diesem Post möchte ich einmal auf genau solche Abhängigkeiten eingehen und schauen, wie man damit umgehen kann.
Auch wenn ich mich eher bei Maven zu Hause fühle, habe ich erst neulich an der Umstellung eines großen Gradle-Projekts auf Java-Module gearbeitet. Da das Projekt Open Source ist, kann es einfach bei GitHub eingesehen werden [1]. In diesem Projekt gab es zu Beginn des Umbaus eine Vielzahl von Abhängigkeiten, die nicht das Java-Modulsystem unterstützt haben. Bei einigen konnten wir eine nachhaltige Lösung erzielen, indem wir direkt Pull Requests (PR) bei den jeweiligen Projekten erstellt haben, um diese um einen Automatic-Module-Name zu ergänzen. Wie man das einfach über ein Maven- oder Gradle-Plug-in erreichen kann, habe ich bereits im vorherigen Post zu dem Thema beschrieben. Ein Beispiel eines solchen PR kann hier [2] gefunden werden.
Nun gibt es aber auch Abhängigkeiten, bei denen man einen solchen PR nicht einfach stellen kann oder bei denen der PR nicht angenommen wird. Vielleicht hat man auch eine Abhängigkeit, deren Weiterentwicklung eingestellt wurde. In allen diesen Fällen wird eine andere Umsetzung benötigt. Im Grunde muss man sich selbst darum kümmern, aus den Abhängigkeiten Java-Module zu erstellen. Hierfür gibt es unterschiedliche Möglichkeiten. Man kann beispielsweise händisch einen Automatic-Module-Name-Eintrag zum Manifest des Jar hinzufügen und die abgeänderte Version dann in einem internen Maven Repository hosten. Für das erwähnte Gradle-Projekt haben wir auf das „extra-java-module-info“-Plug-in von Jendrik Johannes zurückgegriffen. Dieses als Open Source verfügbare Plug-in [3] erlaubt es, zur Build-Zeit einen Automatic-Module-Name Eintrag zu Abhängigkeiten hinzuzufügen. Konkret wird das Plug-in wie in folgendem Beispiel genutzt, wobei bei jedem automaticModule(…) Aufruf der Gradle Identifier der Abhängigkeit als erster Parameter und der zu nutzende Modulname als zweiter Parameter übergeben werden:
plugins {
id("org.gradlex.extra-java-module-info")
}
extraJavaModuleInfo {
failOnMissingModuleInfo.set(true)
automaticModule("io.prometheus:simpleclient",
"io.prometheus.simpleclient")
automaticModule("io.prometheus:simpleclient_common",
"io.prometheus.simpleclient_common")
automaticModule("io.prometheus:simpleclient_httpserver",
"io.prometheus.simpleclient.httpserver")
}
Zusammen mit dem Autor des Plug-ins konnten wir in einem sehr produktiven Austausch das Ganze sogar noch deutlich erweitern. Das Plug-in konnte neben automatischen Modulen schon immer Module mit einer module-info.java erstellen. Hierbei musste man allerdings händisch Angaben wie exports definieren. Durch neue Funktionalitäten kann man nun ein Modul so definieren, dass dessen vollständigen Packages exportiert werden (siehe weitere Infos [4]). Das hat den großen Vorteil, dass man nicht mit automatischen Modulen arbeiten muss, die einige Besonderheiten mich sich bringen, da unter anderem alle automatischen Module zu den „required“ Abhängigkeiten eines Moduls hinzugefügt werden, sobald ein automatischen Modul als „required“ in der module-info.java angegeben ist (siehe Java Spec [5]). Hier noch einmal ein großes Dankeschön an Jendrik Johannes als Maintainer der Bibliothek. Unsere Zusammenarbeit hat aus meiner Sicht extrem gut die Vorteile von Open Source aufgezeigt. Für alle, die hier noch tiefer einsteigen möchten, hat Jendrik mehrere Videos zu diesem Thema und anderen Themen rund um Gradle kostenlos auf YouTube gehostet [6].
Ein letztes großes Problem kann aber auch mit den hier vorgestellten Umsetzungen nicht behoben werden: Sobald ein JAR gegen die package split constraints des Java-Modulsystems verstößt, kann es nicht zum modulepath hinzugefügt werden. In diesem Fall müssen noch deutlich weitreichende Schritte vorgenommen werden. Diesen Punkt werde ich mich aber in einem zukünftigen Beitrag zuwenden.
URL dieses Artikels:
https://www.heise.de/-7536607
Links in diesem Artikel:
[1] https://github.com/hashgraph/hedera-services
[2] https://github.com/offbynull/portmapper/pull/48
[3] https://github.com/gradlex-org/extra-java-module-info
[4] https://github.com/gradlex-org/extra-java-module-info/issues/38
[5] https://docs.oracle.com/javase/specs/jls/se16/html/jls-7.html#jls-7.7.1
[6] https://www.youtube.com/@jjohannes
[7] mailto:rme@ix.de
Copyright © 2023 Heise Medien
(Bild: Shutterstock)
NullPointerExceptions sind mit die häufigste Fehlerquelle in Java. Durch statische Codeanalyse kann man diese Fehler deutlich minimieren.
Neue Projekte bringen neue Herausforderungen und neues Wissen mit sich. In meinem aktuellen Projekt [1] habe ich vor Kurzem eine Definition zum Umgang von null-Checks bei der statischen Codeanalyse erstellt. Vielen im Projekt war es wichtig, dass Parameter nicht nur zur Laufzeit beispielsweise durch Objects.requireNonNull(…)) überprüft werden, sondern auch direkt beim Kompilieren. Daher haben wir beschlossen, hier auch auf statischen Codeanalyse zur Überprüfung des Umgangs mit null zu setzen.
Bevor wir uns auf die verschieben Annotation und Checker Libraries stürzen, die es für Java gibt, möchte ich einmal kurz erläutern, worum es sich bei einer statischen Codeanalyse handelt. Hierbei wird der Programmcode beim Kompilieren durch ein Tooling überprüft. Das aktuell gängigste Tool in Java ist sicherlich SpotBugs, das sich in Builds mit Maven oder Gradle einbinden lässt und dessen Ergebnisse auch automatisiert auf Plattformen wie SonarCloud veröffentlicht werden können. Mit einer statische Codeanalyse kann man Probleme wie einen Speicherüberlauf, eine Endlosschleife oder "Out of Bound“-Fehler finden. Ein einfaches Beispiel ist eine Division durch 0. Sollte so etwas im Code vorkommen, kann die Analyse eine Warnung liefern oder je nach Konfiguration den kompletten Build fehlerhaft beenden. In unserem Projekt haben wir einen solchen Check in GitHub Actions, das die Ergebnisse direkt in SonarCloud [2] und einem Pull Request anzeigt.
Ein Problem beim Programmieren mit Java ist sicherlich der Umgang mit null. Wobei ich persönlich klar die Meinung vertrete, dass null seine Berechtigung hat, auch wenn Tony Hoare, der Erfindern der null-Referenz in der Programmierung, hierüber mittlerweile als ein „Billion-Dollar Mistake“ spricht
Allerdings kann man in Java nicht nativ definieren, ob ein Parameter null sein darf. Das hat man mittlerweile versucht, über verschiedene Mittel in der Klassenbibliothek zu lösen. Beispiele hierfür sind java.util.Optional, Objects.requireNonNull(…) oder auch JSR305 [3].
Ein anschauliches Beispiel für eine Programmiersprache, die eine native Unterstützung für null-Referenzen hat, ist Kotlin. Sie unterscheidet explizit zwischen nullable-Referenzen und nonnull-Referenzen. Hierbei sind Letztere der Standard, wobei einer Variablen mit einer solchen Referenz nie null zugewiesen werden kann. Benötigt man eine Variable, die null umfassen kann, muss man mit einer nullable-Referenz arbeiten. Diese wird über das ? Zeichen angegeben. Der folgende Code beinhaltet ein Kotlin Beispiel für beide Referenzen:
var a: String = "abc" // Regular initialization means
// non-null by default
a = null // compilation error
var b: String? = "abc" // can be set to null
b = null // ok
Da es eine solche native Unterstützung in Java nicht gibt, versucht man sie über statische Codeanalyse so gut wie möglich zu integrieren. Generell werden hier zwei Annotationen benötigt, wobei eine (@Nullable) definiert, dass ein Wert beziehungsweise eine Variable null sein kann, und die andere Annotation definiert, dass ein Wert oder eine Variable nie null sein darf (@NonNull).
Zum Verständnis soll ein Code Beispiel dienen, das eine Methode definiert und per Annotation die Information hinzufügt, dass der Rückgabewert der Methode nie null sein kann:
@NonNull String getName() {
if(isUnique()) {
return „Item „ + getId();
} else {
return null;
}
}
Wie man in der Implementierung der Methode sehen kann, ist es durchaus möglich, dass sie null zurückgibt. Das wär ein Fall, in dem die statische Codeanalyse eine Verletzung aufzeigt. Wer möchte, kann beispielsweise IntelliJ so konfigurieren, dass es solche Probleme direkt anzeigt.
Der folgende Code, der die @Nullable Annotation verwendet, führt zu einer Warnung in der Analyse:
void check(@Nullable String value) {
Objects.hash(value.toLowerCase());
}
In diesem Beispiel wird durch die Annotation @Nullable für die Variable value definiert, dass diese den Wert null haben kann. Dass der Code allerdings direkt auf die Variable zugreift, führt potenziell zu einer NullPointerException zur Laufzeit. Auch das würde durch die statische Codeanalyse ausgewertet und als Problem ausgegeben.
Wer eine solche statische Codeanalyse im eigenen Projekt integrieren möchte, muss ein paar einfache Voraussetzungen schaffen. Als Erstes muss man sich für eins oder mehrere Analysetools entscheiden. Hier empfehle ich Spotbugs [4], das der Nachfolger von Findbugs ist. Das Tool kann entweder über die Kommandozeile oder integriert in einen Gradle oder Maven Build gestartet werden. Um die gefundenen Probleme zu analysieren, kann man sich diese entweder im Spotbugs eigenen Swing-Client anschauen oder beispielsweise als HTML-basierte Übersicht als Bestandteil einer generierten Maven-Site mittels des Maven site-Ziels. Man kann das Tool so konfigurieren, dass es die Ergebnisse beispielsweise in ein Sonar beziehungsweise die SonarCloud hochlädt.
Wer @Nullable- und @NonNull-Annotationen im Projekt nutzen möchte, benötigt eine Library, die die Annotation bereitstellt. Das eigene Projekt muss nur zur Compile-Zeit von der Library abhängig sein. Auch hier gibt es (leider) eine ganze Fülle an Bibliotheken, die Annotationen bereitstellen. Die einzelnen Libraries basierend auf ihren Vor- und Nachteilen zu beleuchten, wird Bestandteil eines eigenen Posts sein. Daher empfehle ich zunächst Spotbugs Annotations als Abhängigkeit, die man unter den folgenden Maven-Koordinaten finden kann:
<dependency>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-annotations</artifactId>
<version>4.7.3</version>
</dependency>
Die Fülle an Tools und Libraries macht es einem bedauerlicherweise nicht leicht, die perfekte und zukunftsorientierte Kombination zu finden. Als ich tiefer in das Thema eingetaucht bin, war ich erschrocken, dass vieles in diesem Bereich noch immer nicht durch Standards oder allgemein genutzte Best Practices definiert ist. Zwar gab es hier verschiedene Ansätze wie etwa mit demJSR305 [5], aber diese sind immer irgendwann im Sande verlaufen und werden heute teils in einem wilden Mix genutzt. Deswegen werde ich auch diesem Problem in naher Zukunft einen eigenen Post widmen.
URL dieses Artikels:
https://www.heise.de/-7351944
Links in diesem Artikel:
[1] https://github.com/hashgraph/hedera-services
[2] https://sonarcloud.io/project/overview?id=com.hedera.hashgraph%3Ahedera-services
[3] https://jcp.org/en/jsr/detail?id=305
[4] https://spotbugs.github.io
[5] https://jcp.org/en/jsr/detail?id=305
[6] mailto:rme@ix.de
Copyright © 2023 Heise Medien

(Bild: Peshkova/Shutterstock.com)
Die jährliche Befragung zu Jakarta EE läuft bis zum 25. Mai. Sie dient der Arbeitsgruppe als Richtlinie für die Weiterentwicklung der Spezifikation.
Jedes Jahr führt die Eclipse Foundation [1] beziehungsweise die Jakarta EE Working Group [2] eine große Umfrage durch, um Informationen zur Nutzung und Verbreitung von Jakarta EE zu sammeln. Diese Daten helfen der Arbeitsgruppe, die Nutzer von Jakarta EE, deren Bedürfnisse und Probleme besser verstehen zu können und sinnvolle Weiterentwicklung und Prioritäten für die Zukunft zu definieren.
Die Ergebnisse der Umfrage bleiben aber nicht nur innerhalb der Arbeitsgruppe, sondern sind als aufbereitetes PDF verfügbar [3]. Die Eclipse Foundation arbeitet die Zahlen grafisch auf. Beispielsweise zeigt folgendes Diagramm aus der letztjährigen Befragung die Beliebtheit der unterschiedlichen Application Server:

Auch 2023 gibt es wieder eine Umfrage, die bis zum 25. Mai online verfügbar ist [4]. Hierbei bitten wir jeden Entwickler und jede Entwicklerin an der Umfrage teilzunehmen, um ein möglichst diverses und breites Bild der Community zu erhalten.
URL dieses Artikels:https://www.heise.de/-8006410
Links in diesem Artikel:[1] https://www.eclipse.org[2] https://jakarta.ee[3] https://outreach.eclipse.foundation/jakarta-ee-developer-survey-2022[4] https://www.surveymonkey.com/r/63FSHRM[5] mailto:rme@ix.de
Copyright © 2023 Heise Medien

Gleisanlagen in Maschen
(Bild: MediaPortal der Deutschen Bahn)
In den letzten Jahren gab es verschiedene Veränderungen im Java Release Train, die zu Verwirrung und Missverständnissen in der Community geführt haben.
Bereits seid dem Release von Java 9 in 2017 werden neue Java-Plattform-Releases durch einen neuen und deutlich besser definierten Release Train veröffentlicht. Leider waren die Aussagen zu den verschiedenen Änderungen und Verbesserungen des Release Train oft nur sehr vage und teils gab es sogar falsche Gerüchte in der Community. Vor allem Oracle hat hier eine schlechte Pressearbeit geliefert und den neuen Release Train nicht so transparent und sauber beschrieben, wie es hätte sein müssen. Da mit dem Release von Java 17 erneut Änderungen in den Release Train eingeflossen sind, möchte ich diesen Post nutzen, um den konkreten Ablauf zu beschreiben.
Bevor wir aber auf den neuen Release Train schauen, ist es sinnvoll, einmal auf die Releases von alten Java-Versionen zu blicken. Das folgende Diagramm zeigt den Release-Zeitpunkt und die Lebensdauer (Lifecycle) von Java 6, 7 und 8. Der Lifecycle der Versionen ist hierbei durch die Verfügbarkeit von kostenlosen Security-Updates der jeweiligen Version definiert. Sobald es für eine der Versionen keine kostenlosen Updates mehr gab oder gibt, endet im Diagramm deren Lebensdauer.

Im Diagramm kann man unterschiedliche Punkte erkennen. Wichtig ist erst einmal, dass immer ein Zeitraum existiert, in dem noch wenigstens zwei Releases mit Security-Updates unterstützt werden. Diese Zeit dient Usern der Plattform als Zeitspanne zur Migration ihrer Anwendungen auf die jeweils neuere Java-Version. Hinzu kommt, dass die Abstände der Releases von neuen Versionen unterschiedlich sind. Das liegt daran, dass diese Java-Versionen veröffentlicht wurden, sobald alle für die jeweilige Version definierten Features implementiert wurden.
Für jede dieser alten Java-Versionen wurden die zu implementierenden Features innerhalb eines Java Specification Requests (JSR) im Java Community Process (JCP) definiert. Für Java 8 kann man beispielsweise unter JSR 337 [1] in Sektion 3 eine Liste der einzelnen Features finden. Diese sind hierbei wiederum auch als JSRs spezifiziert, wobei die Einführung von Lambda-Ausdrücken in Java im JSR 335 und die Date & Time API in JSR 310 definiert wurde.
Da im Vorfeld fest definierte wurde, welche JSRs in einer neuen Java-Version umgesetzt werden sollen, konnte der Release-Zeitpunkt nie fest definiert werden. Das hat teils zu langen Zeitspannen zwischen den Veröffentlichungen der Versionen geführt.
Bei dem gesamten Prozess ist es noch wichtig anzumerken, dass diese Releases keine Versionen sind, die beispielsweise für das Oracle-JDK spezifisch sind. Alle diese Versionen werden im OpenJDK erstellt. Somit kann jeder Java-Vendor einen Build seiner Runtime mit der aktuellen Version anbieten, ohne dass es Unterschiede in der Funktionalität gibt.
Mit Java 9 hat sich diese Vorgehensweise aber stark verändert. Statt langlebiger Releases mit einem unbestimmten Erscheinungsdatum und Lebenszyklus erscheint nun alle sechs Monate ein neues Major Release der Java-Plattform. Das passiert wie bisher im OpenJDK, aber die Sourcen des OpenJDK sind seit Java 17 komplett zu GitHub migriert, wo man die genauen Workflows deutlich besser nachvollziehen kann. Da der Veröffentlichungszeitpunkt eines Release fest definiert ist, können die Features nicht mehr im Vorfeld bestimmt werden. Viel mehr enthält eine neue Java Version alle zu diesem Zeitpunkt abgeschlossen Features. Diese Features werden als JDK Enhancement Proposals (JEP) definiert und können alle auf der Webseite des OpenJDK eingesehen werden [2]. Diese JEPs kann man sich hierbei ähnlich zu Epic Issues vorstellen. Ab Java 10 kann man dann auch auf der jeweiligen Seiten des Releases die Liste der im Release enthaltenen JEPs sehen (siehe Beispiel für Java 11 [3]).
Da manche diese Features längere Zeit zum Entwickeln benötigen und starke Auswirkung auf die Java-Plattform haben, wurde für JEPs der Preview- und Incubator-Status eingeführt. Neue APIs können durch Letzteren bereits zum Testen in Java-Versionen landen, bevor sie in einer künftigen Version finaler Bestandteil der Java-Klassenbibliothek werden. Solche APIs liegen in einem speziellen Incubator Package und werden erst mit ihrem finalen Release an ihr korrektes Package verschoben. Der Preview-Status kann genutzt werden, um neue Sprachfeatures der Java-Plattform bereits im Vorfeld verfügbar zu machen. Solche Features muss man über einen Kommandozeilenparameter aktivieren:
$ javac HelloWorld.java
$ javac --release 14 --enable-preview HelloWorld.java
$ java --enable-preview HelloWorld
Mit einem neuen Release alle sechs Monate hat sich auf die Lebensdauer von Java-Versionen deutlich verändert. Hierbei wird nun zwischen Long-Term Support (LTS) und normalen (non LTS) Versionen unterschieden. Letztere haben eine Lebensdauer von genau sechs Monaten bis zum Release der nächsten Version. So hatte Java 14 eine Lebensspanne von März 2020 bis September 2020. Als LTS gekennzeichnete Versionen werden im OpenJDK länger gepflegt und erhalten über einen längeren Zeitraum Sicherheitsupdates.
Für das LTS-Release Java 17 wird es nach heutigem Kenntnisstand bis 2027 Updates geben. Eine gute Übersicht der LTS Versionen bietet Eclipse Adoptium in der Supportübersicht [4]. Auch wenn LTS-Updates keine neuen Features enthalten, fixen sie doch alle bekannten Sicherheitslücken. Daher heißen solche Releases auch Critical Patch Update (CPU). Für Java-Versionen, die nicht als LTS-Versionen definiert sind, erscheinen zwei geplante CPU-Releases. So wurde für Java 16 nach dem ersten Release im März 2021 die Version 16.0.1 im April 2021 und 16.0.2 im Juli 2021 als CPU veröffentlicht. Mit dem Erscheinen von Java 17 wurde festgelegt, dass es alle zwei Jahre ein neues LTS Release von Java geben wird. Hierdurch wird Java 21 im September 2023 das nächste LTS-Release sein.
Basierend auf diesen Definitionen sieht der Release-Graph der Java Versionen seid Java 9 folgendermaßen aus:

Da alle Arbeit im OpenJDK erfolgt, kann der Veröffentlichungszeitpunkt von einzelnen Java Distributionen leicht abweichen. Sobald das Release im OpenJDK freigegeben ist, startet die Arbeit zum Erstellen der Distributionen wie Eclipse Temurin, Oracle JDK oder Azul Zulu. Hierbei ist jedem Hersteller freigestellt, die Sourcen des OpenJDK um zusätzliche Funktionen zu erweitern, um sich durch Alleinstellungsmerkmal abzuheben. Manche wie Azul oder Bellsoft bündeln beispielsweise JavaFX in ihren Builds.
In früheren Versionen hat vor allem Oracle mit Tools wie WebStart oder Mission Control versucht, sich von anderen OpenJDK-Builds abzuheben. Das hat allerdings zu Kompatibilitätsproblemen in der Community geführt und wird zum Glück heute in der Regel nicht mehr praktiziert.
URL dieses Artikels:https://www.heise.de/-7350614
Links in diesem Artikel:[1] https://www.jcp.org/en/jsr/detail?id=337[2] https://openjdk.java.net/jeps/0[3] https://openjdk.java.net/projects/jdk/11/[4] https://adoptium.net/de/support/[5] mailto:rme@ix.de
Copyright © 2023 Heise Medien