{"id":41295,"date":"2024-12-04T21:37:35","date_gmt":"2024-12-04T20:37:35","guid":{"rendered":"https:\/\/www.happycoders.eu\/?p=41295"},"modified":"2026-04-15T14:57:33","modified_gmt":"2026-04-15T12:57:33","slug":"java-24-features","status":"publish","type":"post","link":"https:\/\/www.happycoders.eu\/de\/java\/java-24-features\/","title":{"rendered":"Java 24 Features (mit Beispielen)"},"content":{"rendered":"\n<p>Java 24 wurde am 18. M\u00e4rz 2025 ver\u00f6ffentlicht. Du kannst es <a href=\"https:\/\/jdk.java.net\/24\/\" target=\"_blank\" rel=\"noopener\">hier<\/a> herunterladen.<\/p>\n\n\n\n<p>In Java 24 wurden ... Trommelwirbel ... exakt 24 JEPs umgesetzt \u2013 nach Java 11 (18 JEPs) ein neuer Rekord! Das h\u00f6rt sich erstmal nach viel an, mit einem Gro\u00dfteil der \u00c4nderungen werden allerdings die meisten von uns im Programmier-Alltag nicht direkt konfrontieren werden.<\/p>\n\n\n\n<p>Hier sind meine pers\u00f6nlichen Highlights:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Die <a href=\"#Stream_Gatherers_JEP_485\">Stream Gatherers API<\/a>, mit der wir unsere eigenen intermedi\u00e4ren Stream-Operationen schreiben k\u00f6nnen, wurde finalisiert.<\/li>\n\n\n\n<li><a href=\"#Synchronize_Virtual_Threads_without_Pinning_JEP_491\">Synchronize Virtual Threads without Pinning<\/a>: In virtuellen Threads d\u00fcrfen wir um blockierenden Code endlich auch <code>synchronized<\/code> verwenden!<\/li>\n\n\n\n<li>Mit <a href=\"#Ahead-of-Time_Class_Loading_Linking_JEP_483\">Ahead-of-Time Class Loading &amp; Linking<\/a> soll die Startzeit insbesondere von kurzlebigen Java-Programmen erheblich verk\u00fcrzt werden.<\/li>\n\n\n\n<li>Mit <a href=\"#Compact_Object_Headers_Experimental_JEP_450\">Compact Object Headers<\/a> wird (aktuell noch experimentell) der Objekt-Header von (in der Regel) 12 Byte auf 8 Byte verk\u00fcrzt und damit der Speicherbederf pro Objekt auf dem Heap um 4 Bytes reduziert. F\u00fcr Anwendungen mit Millionen von Objekten auf dem Heap ist das in Summe eine signifikante Ersparnis.<\/li>\n<\/ul>\n\n\n\n<p>F\u00fcr alle JEPs und sonstigen \u00c4nderungen verwende ich wie immer die originalen, englischen Bezeichnungen.<\/p>\n\n\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"stream-gatherers-jep-485\">Stream Gatherers \u2013 JEP 485<\/h2>\n\n\n\n<p>Vor \u00fcber zehn Jahren wurde in Java 8 die Stream API eingef\u00fchrt. Aufgrund der recht begrenzten Auswahl an intermedi\u00e4ren Operationen \u2013 <em>filter<\/em>, <em>map<\/em>, <em>flatMap<\/em>, <em>mapMulti<\/em>, <em>distinct<\/em>, <em>sorted<\/em>, <em>peak<\/em>, <em>limit<\/em>, <em>skip<\/em>, <em>takeWhile <\/em>und <em>dropWhile<\/em> \u2013 gibt es in der Java-Community laute Rufe nach zus\u00e4tzlichen Operationen wie z. B. <em>window<\/em> oder <em>fold<\/em>.<\/p>\n\n\n\n<p>Doch anstatt all diese Feature-Requests umzusetzen, entschieden sich die JDK-Developer zu einer anderen L\u00f6sung: Sie implementierten eine API, mit der sowohl die JDK-Developer als auch alle anderen Developer selbst intermedi\u00e4re Stream-Operationen implementieren k\u00f6nnen.<\/p>\n\n\n\n<p>Diese neue API hei\u00dft \u201eStream Gatherers\u201d. Sie wurde erstmals in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-22-features\/#Stream_Gatherers_Preview_JEP_461\">Java 22<\/a> als Preview-Version vorgestellt und ging in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-23-features\/#Stream_Gatherers_Second_Preview_JEP_473\">Java 23<\/a> ohne \u00c4nderungen in eine zweite Preview-Runde.<\/p>\n\n\n\n<p>In Java 24 wird die Stream Gatherers API durch <a href=\"https:\/\/openjdk.org\/jeps\/485\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 485<\/a> finalisiert \u2013 erneut ohne \u00c4nderungen.<\/p>\n\n\n\n<p>Der folgende Code zeigt beispielsweise, wie wir die intermedi\u00e4re Stream-Operation \u201efilter\u201d als Stream Gatherer implementieren und verwenden k\u00f6nnen. Das kurze Programm zeigt all diejenigen Strings an, die mindestens 3 Zeichen lang sind:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n  List&lt;String&gt; words = List.of(<span class=\"hljs-string\">\"the\"<\/span>, <span class=\"hljs-string\">\"be\"<\/span>, <span class=\"hljs-string\">\"two\"<\/span>, <span class=\"hljs-string\">\"of\"<\/span>, <span class=\"hljs-string\">\"and\"<\/span>, <span class=\"hljs-string\">\"a\"<\/span>, <span class=\"hljs-string\">\"in\"<\/span>, <span class=\"hljs-string\">\"that\"<\/span>);\n\n  List&lt;String&gt; list = words.stream()\n      .gather(filtering(string -&gt; string.length() &gt;= <span class=\"hljs-number\">3<\/span>))\n      .toList();\n\n  System.out.println(list);\n}\n\n<span class=\"hljs-keyword\">private<\/span> &lt;T&gt; <span class=\"hljs-function\">Gatherer&lt;T, Void, T&gt; <span class=\"hljs-title\">filtering<\/span><span class=\"hljs-params\">(Predicate&lt;T&gt; predicate)<\/span> <\/span>{\n  <span class=\"hljs-keyword\">return<\/span> Gatherer.of(Gatherer.Integrator.ofGreedy(\n      (_, element, downstream) -&gt; {\n        <span class=\"hljs-keyword\">if<\/span> (predicate.test(element)) {\n          <span class=\"hljs-keyword\">return<\/span> downstream.push(element);\n        } <span class=\"hljs-keyword\">else<\/span> {\n          <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">true<\/span>;\n        }\n      }));\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Was sind die Komponenten dieses Programms, und wie funktionieren sie?<\/p>\n\n\n\n<p>Wie implementiert man komplexere Stream Gatherer, und welche Einschr\u00e4nkungen gibt es dabei?<\/p>\n\n\n\n<p>Welche vordefinierten Stream Gatherer liefert Java 24 mit?<\/p>\n\n\n\n<p>All das erf\u00e4hrst du im <a href=\"https:\/\/www.happycoders.eu\/de\/java\/stream-gatherers\/\">Hauptartikel \u00fcber Stream Gatherers<\/a> ... oder bei meinem <a href=\"https:\/\/meine.doag.org\/events\/javaland\/2025\/agenda\/#eventDay.all#textSearch.Stream%20Gatherers:%20Schreibt%20eure%20eigenen,%20leistungsstarken%20Stream-Operationen!\" target=\"_blank\" rel=\"noopener\">Stream-Gatherers-Vortrag auf der JavaLand 2025<\/a> :-)<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><a href=\"https:\/\/meine.doag.org\/events\/javaland\/2025\/agenda\/#eventDay.all#textSearch.Stream%20Gatherers:%20Schreibt%20eure%20eigenen,%20leistungsstarken%20Stream-Operationen!\" target=\"_blank\" rel=\" noopener\"><img decoding=\"async\" width=\"513\" height=\"257\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/javaland_2025-banner-512x256px-ich_bin_speaker.jpg\" alt=\"javaland 2025 banner 512x256px ich bin speaker\" class=\"wp-image-42374\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/javaland_2025-banner-512x256px-ich_bin_speaker.jpg 513w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/javaland_2025-banner-512x256px-ich_bin_speaker-224x112.jpg 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/javaland_2025-banner-512x256px-ich_bin_speaker-336x168.jpg 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/javaland_2025-banner-512x256px-ich_bin_speaker-504x252.jpg 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/javaland_2025-banner-512x256px-ich_bin_speaker-400x200.jpg 400w\" sizes=\"(max-width: 513px) 100vw, 513px\" \/><\/a><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"synchronize-virtual-threads-without-pinning-jep-491\">Synchronize Virtual Threads without Pinning \u2013 JEP 491<\/h2>\n\n\n\n<p>Seit ihrer Einf\u00fchrung in Java 21 wurden <a href=\"https:\/\/www.happycoders.eu\/de\/java\/virtual-threads\/\">virtuelle Threads<\/a> beim Aufruf von blockierendem Code innerhalb eines <code>synchronized<\/code>-Blocks an ihren Carrier Thread \u201egepinnt\u201c, d. h. der Carrier Thread wurde blockiert und konnte w\u00e4hrenddessen keine anderen virtuellen Threads bedienen. Das konnte ganze Anwendungen einfrieren lassen, wie z. B. <a href=\"https:\/\/netflixtechblog.com\/java-21-virtual-threads-dude-wheres-my-lock-3052540e231d\" target=\"_blank\" rel=\"noopener\">in dem hier anschaulich beschriebenen Fall bei Netflix<\/a>.<\/p>\n\n\n\n<p>Ab Java 24 geh\u00f6rt dieses Problem der Vergangenenheit an. Beim Aufruf von blockierendem Code innerhalb eines <code>synchronized<\/code>-Blocks wird der virtuelle Thread nun vom Carrier Thread gel\u00f6st, und dieser kann andere virtuelle Threads ausf\u00fchren.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Warum wurden virtuelle Threads \u201egepinnt\u201c?<\/h4>\n\n\n\n<p>Zum einen wurde beim sogenannten <a href=\"https:\/\/www.happycoders.eu\/de\/java\/object-headers-compressed-class-pointers\/#legacy-stack-locking\">Legacy Stack Locking<\/a> beim Aufruf eines <code>synchronized<\/code>-Blocks das <a href=\"https:\/\/www.happycoders.eu\/de\/java\/object-headers-compressed-class-pointers\/#mark-word\">Mark Word des Objekt-Headers<\/a> durch einen Pointer auf eine Speicheradresse auf dem Thread-Stack ersetzt. Da der Stack beim Unmounten eines virtuellen Threads auf den Heap verschoben wird und beim Mounten zur\u00fcck auf den Stack \u2013 m\u00f6glicherweise aber auf den Stack eines anderen Carrier Threads \u2013 w\u00e4re diese Speicheradresse dadurch ung\u00fcltig geworden.<\/p>\n\n\n\n<p>Dieses Problem wird durch das seit Java 23 standardm\u00e4\u00dfig aktivierte <a href=\"https:\/\/www.happycoders.eu\/de\/java\/object-headers-compressed-class-pointers\/#lightweight-locking\">Lightweight Locking<\/a> gel\u00f6st, das ohne \u00c4nderung des Mark Words auskommt.<\/p>\n\n\n\n<p>Zum anderen merkt sich die JVM beim Aufruf eines <code>synchronized<\/code>-Blocks, welcher <em>Plattform<\/em>-Thread sich in dem Block befindet, nicht welcher virtuelle Thread. Wenn nun der virtuelle Thread vom Carrier Thread genommen und ein anderer virtueller Thread auf diesen Carrier gemounted wird, dann k\u00f6nnte dieser andere virtuelle Thread ebenfalls den <code>synchronized<\/code>-Block betreten.<\/p>\n\n\n\n<p>Warum merkt sich die JVM den Plattform-Thread und nicht den virtuellen Thread? Ganz einfach: der JVM-Code ist komplex, und die JDK-Entwickler hatten es bis zur Ver\u00f6ffentlichung von Java 21 einfach nicht rechtzeitig geschafft, ihn anzupassen.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Pinning bei Aufruf von nativem Code<\/h4>\n\n\n\n<p>Auch nativer Code (aufgerufen via JNI oder <a href=\"https:\/\/www.happycoders.eu\/de\/java\/foreign-function-memory-api\/\">FFM-API<\/a>) k\u00f6nnte mit Pointern auf den Thread-Stack arbeiten, die nach dem Unmounten und Mounten eines virtuellen Threads auf einem anderen Carrier Thread ung\u00fcltig werden w\u00fcrden. Daher wird beim Aufruf von nativem Code ein virtueller Thread weiterhin an seinen Carrier Thread gepinnt. <\/p>\n\n\n\n<p>Daran \u00e4ndert sich durch diesen JEP und vermutlich auch zuk\u00fcnftig nichts.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Die Diagnose-Property jdk.tracePinnedThreads wird entfernt<\/h4>\n\n\n\n<p>Mit der System Property <code>jdk.tracePinnedThreads<\/code> konnte man sich einen Stacktrace ausgeben lassen, sobald ein virtueller Thread einen <code>synchronized<\/code> Block betreten hat und dadurch an seinen Carrier gepinnt wurde. Da die Ausgabe innerhalb des <code>synchronized<\/code> Blocks erfolgte, wurde die Dauer des Pinnings dadurch noch verl\u00e4ngert.<\/p>\n\n\n\n<p>Die Property wurde in Java 24 ersatzlos entfernt.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"ahead-of-time-class-loading-linking-jep-483\">Ahead-of-Time Class Loading &amp; Linking \u2013 JEP 483<\/h2>\n\n\n\n<p>Java-Anwendungen sind extrem flexibel und performant:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Klassen k\u00f6nnen dynamisch ge- und entladen werden.<\/li>\n\n\n\n<li>Durch dynamische Compilierung, Optimierung und Re-Optimierung laufen sie teilweise schneller als C-Code.<\/li>\n\n\n\n<li>Reflection erm\u00f6glicht Enterprise-Frameworks wie Jakarta EE und Spring Boot.<\/li>\n<\/ul>\n\n\n\n<p>Doch daf\u00fcr m\u00fcssen beim Start Tausende von Klassen gelesen, geparst, geladen und gelinkt werden, was besonders bei gro\u00dfen Backend-Anwendungen zu langen Startzeiten f\u00fchren kann.<\/p>\n\n\n\n<p>Innerhalb von <a href=\"https:\/\/openjdk.org\/projects\/leyden\/\" target=\"_blank\" rel=\"noopener\">Project Leyden<\/a> wird seit langem an L\u00f6sungen daf\u00fcr gearbeitet, m\u00f6glichst viele dieser vorbereitenden Aufgaben bereits <em>vor<\/em> dem Start einer Anwendung auszuf\u00fchren. Durch <a href=\"https:\/\/openjdk.org\/jeps\/483\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 483<\/a> wird in Java 24 die erste dieser L\u00f6sungen vorgestellt: <em>Ahead-of-Time Class Loading &amp; Linking<\/em>.<\/p>\n\n\n\n<p>Dabei werden in einer Vorbereitungsphase alle von der Anwendung ben\u00f6tigten Klassen gelesen, geparst, geladen und gelinkt und dann in diesem Zustand in einem Cache gespeichert. Beim Start der Anwendung m\u00fcssen diese Schritte dann nicht mehr ausgef\u00fchrt werden; die Anwendung kann auf die geladenen und gelinkten Klassen direkt \u00fcber den Cache zugreifen.<\/p>\n\n\n\n<p>Weitere Details zur Funktionsweise, eine Schritt-f\u00fcr-Schritt-Anleitung zum Ausprobieren und eine Gegen\u00fcberstellung mit AppCDS (Application Class Data Sharing) findest du im Hauptartikel <a href=\"https:\/\/www.happycoders.eu\/de\/java\/ahead-of-time-class-loading-and-linking\/\">Ahead-of-Time Class Loading &amp; Linking<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"neue-preview-und-experimental-features-in-java-24\">Neue Preview- und Experimental Features in Java 24<\/h2>\n\n\n\n<p>In Java 24 gibt es ein neues Preview-Feature und zwei experimentelle Previews.<\/p>\n\n\n\n<p>Diese Features sind zum Ausprobieren und Feedback geben gedacht. Sie sollten nicht unbedingt in Produktivcode eingesetzt werden, da sie sich noch \u00e4ndern oder \u2013 wie im Fall von String Templates \u2013 auch wieder komplett entfernt werden k\u00f6nnen.<\/p>\n\n\n\n<p>Preview-Features m\u00fcssen im Java-Compiler <code>javac<\/code> mit <code>--enable-preview --source 24<\/code> aktiviert werden. Beim Start eines Programms mit dem <code>java<\/code>-Kommando gen\u00fcgt <code>--enable-preview<\/code>.<\/p>\n\n\n\n<p>Experimentelle Features werden zur Laufzeit mit <code>-XX:+UnlockExperimentalVMOptions<\/code> aktiviert.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"key-derivation-function-api-preview-jep-478\">Key Derivation Function API (Preview) \u2013 JEP 478<\/h3>\n\n\n\n<p>Eine Key Derivation Function (KDF, deutsch: Schl\u00fcsselableitungsfunktion) ist eine Methode, um aus einem geheimen Wert wie einem Passwort, einer Passphrase oder einem kryptographischen Schl\u00fcssel einen oder mehrere neue kryptographische Schl\u00fcssel abzuleiten.<\/p>\n\n\n\n<p>Damit Sicherheitsanbieter KDF-Algorithmen implementieren und anbieten k\u00f6nnen und wir sie in Anwendungen einsetzen k\u00f6nnen, bedarf es einer einheitlichen API.<\/p>\n\n\n\n<p>Solch eine API wird durch <a href=\"https:\/\/openjdk.org\/jeps\/478\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 478<\/a> bereitgestellt: \u00fcber die neue Klasse <code>javax.crypto.KDF<\/code> k\u00f6nnen Key Derivation Functions geladen und aufgerufen werden.<\/p>\n\n\n\n<p>Der folgende Beispielcode zeigt, wie du \u00fcber den KDF-Algorithmus \"HKDF-SHA256\" aus einem Passwort bzw. einer Passphrase und einem Salt einen AES-Key erzeugen kannst. <\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">()<\/span> <span class=\"hljs-keyword\">throws<\/span> InvalidAlgorithmParameterException, NoSuchAlgorithmException <\/span>{\n  <span class=\"hljs-comment\">\/\/ 1. Get the implementation of the specified KDF algorithm<\/span>\n  KDF hkdf = KDF.getInstance(<span class=\"hljs-string\">\"HKDF-SHA256\"<\/span>);\n\n  <span class=\"hljs-comment\">\/\/ 2. Specify the derivation parameters<\/span>\n  AlgorithmParameterSpec params =\n      HKDFParameterSpec.ofExtract()\n          <span class=\"hljs-comment\">\/\/ 2.1. The password \/ passphrase<\/span>\n          .addIKM(<span class=\"hljs-string\">\"the super secret passphrase\"<\/span>.getBytes(StandardCharsets.UTF_8))\n          <span class=\"hljs-comment\">\/\/ 2.2. The salt value<\/span>\n          .addSalt(<span class=\"hljs-string\">\"the salt\"<\/span>.getBytes(StandardCharsets.UTF_8))\n          <span class=\"hljs-comment\">\/\/ 2.3. Optional application-specific information<\/span>\n          .thenExpand(<span class=\"hljs-string\">\"my derived key\"<\/span>.getBytes(StandardCharsets.UTF_8), <span class=\"hljs-number\">32<\/span>);\n\n  <span class=\"hljs-comment\">\/\/ 3. Derive a 32-byte AES keys<\/span>\n  SecretKey key = hkdf.deriveKey(<span class=\"hljs-string\">\"AES\"<\/span>, params);\n\n  System.out.println(<span class=\"hljs-string\">\"key = \"<\/span> + HexFormat.of().formatHex(key.getEncoded()));\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Falls du dich \u00fcber die fehlende Klassendeklaration, fehlende Imports und das kurze <code>void main()<\/code> statt des gewohnten <code>public static void main(String[] args)<\/code> wunderst \u2013 diese Vereinfachungen werden im Abschnitt <a href=\"#simple-source-files-and-instance-main-methods-fourth-preview-jep-495\">Simple Source Files and Instance Main Methods<\/a> beschrieben.<\/p>\n\n\n\n<div class=\"wp-block-columns has-background is-layout-flex wp-container-core-columns-is-layout-f5fea6a2 wp-block-columns-is-layout-flex\" style=\"background-color:#f1f6f9;padding-top:24px;padding-right:24px;padding-bottom:24px;padding-left:24px;font-size:clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.196), 16px);\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:30px\">      \n\t\t\t<div class=\"uagb-icon-wrapper uagb-block-ea1c6094      \"\n\t\t\tstyle=\"\" >\n\t\t\t\t\t\t\t\t\t<span class=\"uagb-svg-wrapper\" \n\t\t\t\t\t aria-label=\"circle-info\"\t\t\t\t\ttabindex=\"0\">\t\t\n\t\t\t\t\t\t\t\t\t\t<svg xmlns=\"https:\/\/www.w3.org\/2000\/svg\" viewBox= \"0 0 512 512\" role=\"graphics-symbol\" aria-hidden=\"false\" aria-label=\"\"><path d=\"M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM256 128c17.67 0 32 14.33 32 32c0 17.67-14.33 32-32 32S224 177.7 224 160C224 142.3 238.3 128 256 128zM296 384h-80C202.8 384 192 373.3 192 360s10.75-24 24-24h16v-64H224c-13.25 0-24-10.75-24-24S210.8 224 224 224h32c13.25 0 24 10.75 24 24v88h16c13.25 0 24 10.75 24 24S309.3 384 296 384z\"><\/path><\/svg>\n\t\t\t\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t<\/div>\n\t\t\t<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\" style=\"flex-basis:100%\">\n<p>Im Quellcode finden sich eine ganze Menge Abk\u00fcrzungen. Eine Erl\u00e4uterung dieser Konzpete w\u00fcrde den Rahmen dieses Artikels sprengen, daher habe ich dir ein paar Links zu Wikipedia-Artikeln zusammengestellt:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>HKDF steht f\u00fcr <a href=\"https:\/\/en.wikipedia.org\/wiki\/HKDF\" target=\"_blank\" rel=\"noopener\">HMAC Key Derivation Function<\/a>.<\/li>\n\n\n\n<li>HMAC wiederum steht f\u00fcr <a href=\"https:\/\/de.wikipedia.org\/wiki\/HMAC\" target=\"_blank\" rel=\"noopener\">Hash-based Message Authentication Code<\/a>.<\/li>\n\n\n\n<li>IKM steht f\u00fcr \u201einput key material\u201c \u2013 das kann ein Passwort, eine Passphrase oder auch ein anderer kryptografischer Schl\u00fcssel sein.<\/li>\n\n\n\n<li>AES steht f\u00fcr <a href=\"https:\/\/de.wikipedia.org\/wiki\/Advanced_Encryption_Standard\" target=\"_blank\" rel=\"noopener\">Advanced Encryption Standard<\/a>.<\/li>\n<\/ul>\n<\/div>\n<\/div>\n\n\n\n<p>Wenn du den oben gezeigten Quellcode in der Datei <em>KDFTest.java<\/em> speicherst, kannst du ihn mit Java 24 wie folgt aufrufen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">java --enable-preview KDFTest.java<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Klartext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Bei mir f\u00fchrt das zum Beispiel zu folgender Ausgabe:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">key = 7ee15549ddce956194ca1d6df5aa34c1a1334d15c875e67ea67fb5850ee48b0c<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Klartext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Dieser Key kann dann z. B. als Session Key f\u00fcr die verschl\u00fcsselte Daten\u00fcbertragung verwendet werden.<\/p>\n\n\n\n<p>Die Key Derivation Function API wird in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-25-features\/\">Java 25<\/a> finalisiert.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"generational-shenandoah-experimental-jep-404\">Generational Shenandoah (Experimental) \u2013 JEP 404<\/h3>\n\n\n\n<p>In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-15-features\/\">Java 15<\/a> wurden mit ZGC und Shenandoah zwei neue Garbage Collectoren eingef\u00fchrt. Beide versprechen extrem niedrige Pausenzeiten von weniger als 10 Millisekunden.<\/p>\n\n\n\n<p>Zum Zeitpunkt ihrer Einf\u00fchrung machten diese GCs keinen Unterschied zwischen \u201ealten\u201d und \u201eneuen\u201d Objekten. Somit machten sie sich nicht die sogenannte \u201eSchwache Generationshypothese\u201d (englisch: \u201eWeak Generational Hypothesis\u201d) zunutze, die besagt, dass die meisten Objekte kurz nach ihrer Entstehung wieder sterben, und dass diejenigen Objekte, die bereits ein gewisses Alter erreicht haben, in der Regel auch noch l\u00e4nger leben werden.<\/p>\n\n\n\n<p>Ein \u201eGenerational Garbage Collector\u201d nutzt diese Hypothese, in dem er den Heap in zwei logische Bereiche aufteilt: eine \u201ejunge Generation\u201d und eine \u201ealte Generation\u201d. In der jungen Generation werden neue Objekte angelegt, und wenn diese einige GC-Zyklen \u00fcberstanden haben, werden sie in die alte Generation verschoben. Da die Wahrscheinlichkeit hoch ist, dass die Objekte in der alten Generation l\u00e4nger leben, kann der Garbage Collector die Leistung einer Anwendung erh\u00f6hen, indem er die alte Generation seltener aufr\u00e4umt.<\/p>\n\n\n\n<p>In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-21-features\/#Generational_ZGC_JEP_439\">Java 21<\/a> wurde dann ein \u201eGenerational Mode\u201d f\u00fcr den ZGC vorgestellt, der seit <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-23-features\/#ZGC_Generational_Mode_by_Default_JEP_474\">Java 23<\/a> standardm\u00e4\u00dfig aktiviert ist.<\/p>\n\n\n\n<p>Urspr\u00fcnglich war in Java 21 dieser Modus auch f\u00fcr Shenandoah eingeplant, doch das Shenandoah-Team zog den JEP kurz vor der Ver\u00f6ffentlichung zur\u00fcck, da die Implementierung noch nicht ausgereift war.<\/p>\n\n\n\n<p>Jetzt ist es endlich so weit: In Java 24 wird nun auch f\u00fcr Shenandoah der \u201eGenerational Mode\u201d eingef\u00fchrt. Dieser Modus befindet sich aktuell noch im Versuchsstadium und kann wie folgt aktiviert werden:<\/p>\n\n\n\n<p class=\"has-text-align-center\"><code>-XX:+UnlockExperimentalVMOptions -XX:ShenandoahGCMode=generational<\/code><\/p>\n\n\n\n<p>Die \u00c4nderungen werden in <a href=\"https:\/\/openjdk.org\/jeps\/404\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 404<\/a> beschrieben \u2013 allerdings recht oberfl\u00e4chlich. Falls du dich f\u00fcr die Funktionsweise eines Generational Garbage Collectors interessierst, empfehle ich dir den sehr detaillierten <a href=\"https:\/\/openjdk.org\/jeps\/439\" target=\"_blank\" rel=\"noopener\">JEP 439<\/a> (Generational ZGC) zu lesen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"compact-object-headers-experimental-jep-450\">Compact Object Headers (Experimental) \u2013 JEP 450<\/h3>\n\n\n\n<p>Der <a href=\"https:\/\/www.happycoders.eu\/de\/java\/object-headers-compressed-class-pointers\/\">Java-Objekt-Header<\/a> ist aktuell in der Regel 12 Byte gro\u00df (bzw. 16 Byte, wenn <a href=\"https:\/\/www.happycoders.eu\/de\/java\/object-headers-compressed-class-pointers\/#compressed-class-pointers\">Compressed Class Pointers<\/a> ausgeschaltet sind). Um den Speicherbedarf von Java-Anwendungen zu reduzieren, arbeiten die JDK-Entwickler im Rahmen von <a href=\"https:\/\/wiki.openjdk.org\/spaces\/lilliput\/overview\" target=\"_blank\" rel=\"noreferrer noopener\">Project Lilliput<\/a> an M\u00f6glichkeiten, um den Header auf 8 Byte \u2013 und im n\u00e4chsten Schritt auf 4 Byte \u2013 zu komprimieren.<\/p>\n\n\n\n<p>In Java 24 wurde das erste, vielversprechende Resultat aus Project Lilliput vorgestellt: Durch <a href=\"https:\/\/openjdk.org\/jeps\/450\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 450<\/a> kann der Objekt-Header auf 8 Byte komprimiert werden (aktuell noch im \u201eExperimental\u201c-Status).<\/p>\n\n\n\n<p>Wie haben die JDK-Developer das erreicht?<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Status Quo<\/h4>\n\n\n\n<p>Ein 12-Byte-Object-Header besteht aus einem 64-Bit Mark Word und einem 32-Bit Class Word:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full_800\"><img decoding=\"async\" width=\"800\" height=\"217\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-java-object-header-mark-word-class-word.v3-800x217.png\" alt=\"JEP 450: Java Object Header with Mark Word and Class Word\" class=\"wp-image-41735\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-java-object-header-mark-word-class-word.v3-800x217.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-java-object-header-mark-word-class-word.v3-224x61.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-java-object-header-mark-word-class-word.v3-336x91.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-java-object-header-mark-word-class-word.v3-504x137.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-java-object-header-mark-word-class-word.v3-672x182.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-java-object-header-mark-word-class-word.v3-400x109.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-java-object-header-mark-word-class-word.v3-600x163.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-java-object-header-mark-word-class-word.v3-944x256.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-java-object-header-mark-word-class-word.v3-1200x326.png 1200w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-java-object-header-mark-word-class-word.v3.png 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/figure>\n<\/div>\n\n\n<p>Das Mark Word enth\u00e4lt:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>27 ungenutzte Bits (25 am Anfang und je eines vor und nach dem \u201eAge Tag\u201c),<\/li>\n\n\n\n<li>den 31 Bit langen Identity Hash Code,<\/li>\n\n\n\n<li>4 Bits, in denen der Garbage Collector das Alter eines Objekts speichert,<\/li>\n\n\n\n<li>2 \u201eTag Bits\u201c, die anzeigen, ob und wie das Objekt gelockt ist.<\/li>\n<\/ul>\n\n\n\n<p>Das Class Word enth\u00e4lt:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>einen 32-Bit-Pointer auf die sogenannte <em>Klass<\/em>-Datenstruktur, in der die Informationen der Klasse gespeichert sind, von der das Objekt eine Instanz ist.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Komprimierung des Objekt-Headers<\/h4>\n\n\n\n<p>Das Mark Word enth\u00e4lt 27 ungenutzte Bits. Von den insgesamt 96 Bits werden also nur 69 Bits ben\u00f6tigt. Um auf 64 Bit zu kommen, m\u00fcssen wir f\u00fcnf Bits einsparen. Folgendes kam dabei heraus:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full_800\"><img decoding=\"async\" width=\"800\" height=\"174\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-compact-object-header-java.v2-800x174.png\" alt=\"JEP 450: Compact Object Header\" class=\"wp-image-41736\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-compact-object-header-java.v2-800x174.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-compact-object-header-java.v2-224x49.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-compact-object-header-java.v2-336x73.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-compact-object-header-java.v2-504x110.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-compact-object-header-java.v2-672x146.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-compact-object-header-java.v2-400x87.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-compact-object-header-java.v2-600x131.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-compact-object-header-java.v2-944x205.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-compact-object-header-java.v2-1200x261.png 1200w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-450-compact-object-header-java.v2.png 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/figure>\n<\/div>\n\n\n<p>Wir haben nun einen 64 Bit-Header, der nicht mehr in Mark Word und Class Word unterteilt ist. Der Header enth\u00e4lt:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>einen auf 22 Bit komprimierten Class Pointer,<\/li>\n\n\n\n<li>den 31-Bit Identity Hash Code (unver\u00e4ndert),<\/li>\n\n\n\n<li>4 f\u00fcr <a href=\"https:\/\/openjdk.org\/projects\/valhalla\/\" target=\"_blank\" rel=\"noopener\">Project Valhalla<\/a> reservierte Bits (neu),<\/li>\n\n\n\n<li>4 Bits f\u00fcr das Alter des Objekts (unver\u00e4ndert),<\/li>\n\n\n\n<li>1 Bit f\u00fcr das sogenannte \u201eSelf Forwarded Tag\u201c,<\/li>\n\n\n\n<li>2 Tag Bits (unver\u00e4ndert).<\/li>\n<\/ul>\n\n\n\n<p>Der Class Pointer wurde also um 10 Bits verkleinert. Da wir nur f\u00fcnf Bits einsparen mussten, stehen nun f\u00fcnf zus\u00e4tzliche Bits zur Verf\u00fcgung. Vier davon wurden f\u00fcr Projekt Valhalla reserviert, und in einem Bit wird das neue \u201eSelf Forwarded Tag\u201c gespeichert.<\/p>\n\n\n\n<p>Wie es den JDK-Developern gelang, den Class Pointer von 32 Bit auf 22 Bit zu komprimieren und was das \u201eSelf Forwarded Tag\u201c ist, erf\u00e4hrst du im <a href=\"https:\/\/www.happycoders.eu\/de\/java\/compact-object-headers\/\">Hauptartikel \u00fcber Compact Object Headers<\/a>.<\/p>\n\n\n\n<p>Compact Object Headers befinden sich in Java 24 noch im experimentellen Stadium und m\u00fcssen mit folgender VM-Option aktiviert werden:<\/p>\n\n\n\n<p class=\"has-text-align-center\"><code>-XX:+UnlockExperimentalVMOptions -XX:+UseCompactObjectHeaders<\/code><\/p>\n\n\n<div class=\"convertkit-form wp-block-convertkit-form\" style=\"\"><script async data-uid=\"1427197203\" src=\"https:\/\/happycoders.kit.com\/1427197203\/index.js\" data-jetpack-boost=\"ignore\" data-no-defer=\"1\" data-no-optimize=\"1\" nowprocket><\/script><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"wiedervorgelegte-preview-und-incubator-features\">Wiedervorgelegte Preview und Incubator-Features<\/h2>\n\n\n\n<p>Ganze sieben Preview- und Incubator-JEPs wurden in Java 24 wiedervorgelegt \u2013 vier davon ohne \u00c4nderungen gegen\u00fcber Java 23, eines mit \u00c4nderungen nur in der Terminologie und zwei mit kleineren \u00c4nderungen. Welche das sind, erf\u00e4hrst du in den n\u00e4chsten Abschnitten.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"primitive-types-in-patterns-instanceof-and-switch-second-preview-jep-488\">Primitive Types in Patterns, instanceof, and switch (Second Preview) \u2013 JEP 488<\/h3>\n\n\n\n<p>In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-16-features\/#Pattern_Matching_for_instanceof\">Java 16<\/a> wurde Pattern Matching mit <em>instanceof<\/em> eingef\u00fchrt und in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-21-features\/#Pattern_Matching_for_switch_JEP_441\">Java 21<\/a> Pattern Matching mit <em>switch<\/em>.<\/p>\n\n\n\n<p>Das folgende <code>switch<\/code>-Statement pr\u00fcft beispielsweise, ob das Objekt <code>obj<\/code> ein mindestens f\u00fcnf Zeichen langer String ist und gibt diesen dann, in Gro\u00dfbuchstaben umgewandelt aus. Wenn das Objekt hingegen ein Integer ist, wird die Zahl quadriert und ausgegeben:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">switch<\/span> (obj) {\n  <span class=\"hljs-keyword\">case<\/span> String s when s.length() &gt;= <span class=\"hljs-number\">5<\/span> -&gt; System.out.println(s.toUpperCase());\n  <span class=\"hljs-keyword\">case<\/span> Integer i                     -&gt; System.out.println(i * i);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">null<\/span>, <span class=\"hljs-keyword\">default<\/span>                 -&gt; System.out.println(obj);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Auf diese Weise konnten wir bisher nur <em>Objekte<\/em> mit Mustern abgleichen, nicht jedoch primitive Datentypen wie <code>int<\/code>, <code>long<\/code> oder <code>double<\/code>.<\/p>\n\n\n\n<p>Was wir allerdings schon immer in einem <code>switch<\/code> machen konnten (wenn auch nicht in der modernen Pfeil-Notation), war z. B. eine <code>int<\/code>-Variable mit Konstanten zu vergleichen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">int<\/span> code = . . .\n<span class=\"hljs-keyword\">switch<\/span> (code) {\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-number\">200<\/span> -&gt; System.out.println(<span class=\"hljs-string\">\"OK\"<\/span>);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-number\">400<\/span> -&gt; System.out.println(<span class=\"hljs-string\">\"Bad Request\"<\/span>);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-number\">404<\/span> -&gt; System.out.println(<span class=\"hljs-string\">\"Not Found\"<\/span>);\n  . . .\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Aber Achtung: das funktionierte bisher nur mit den primitiven Datentypen <code>byte<\/code>, <code>short<\/code>, <code>char<\/code> und <code>int<\/code> \u2013 nicht hingegen mit <code>long<\/code>,<code>float<\/code>, <code>double<\/code> und <code>boolean<\/code>.<\/p>\n\n\n\n<p>Durch \u201ePrimitive Types in Patterns, instanceof, and switch\u201c \u2013 erstmals in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-23-features\/#primitive-types-in-patterns-instanceof-and-switch-preview-jep-455\">Java 23<\/a> durch <a href=\"https:\/\/openjdk.org\/jeps\/455\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 455<\/a> vorgestellt und in Java 24 durch <a href=\"https:\/\/openjdk.org\/jeps\/488\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 488<\/a> ohne \u00c4nderungen wiedervorgelegt \u2013 werden sich zwei Dinge \u00e4ndern:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Im Pattern Matching mit <em>instanceof<\/em> und <em>switch<\/em> k\u00f6nnen wir in Zukunft auch primitive Typen verwenden.<\/li>\n\n\n\n<li>In switch d\u00fcrfen wir <em>alle<\/em> primitiven Typen verwenden, also auch <code>long<\/code>, <code>float<\/code>, <code>double<\/code> \u2013 und sogar <code>boolean<\/code>.<\/li>\n<\/ol>\n\n\n\n<p>Pattern Matching mit primitiven Typen unterscheidet sich allerdings vom Pattern Matching mit Referenztypen:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Beim Pattern Matching mit Referenztypen pr\u00fcfen wir, ob ein Objekt eine Instanz eines bestimmten Typs (Klasse oder Interface) ist oder Instanz eines von diesem Typen direkt oder indirekt abgeleiteten Typen. Eine Variable vom Typ <code>Integer<\/code> beispielsweise w\u00fcrde auf das Pattern <code>Integer i<\/code>, aber auch auf die Pattern <code>Number n<\/code>, <code>Object o<\/code> oder sogar <code>Comparable c<\/code> oder <code>Serializable s<\/code> matchen.<\/li>\n\n\n\n<li>Beim Pattern Matching mit primitiven Typen hingegen pr\u00fcfen wir, ob sich eine Variable ohne Pr\u00e4zisionsverlust im zu matchenden Typen speichern l\u00e4sst.<\/li>\n<\/ul>\n\n\n\n<p>Das h\u00f6rt sich erstmal kompliziert an, ist aber an einem Beispiel schnell erkl\u00e4rt:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">int<\/span> i = . . .\n<span class=\"hljs-keyword\">if<\/span> (i <span class=\"hljs-keyword\">instanceof<\/span> <span class=\"hljs-keyword\">byte<\/span> b) {\n  . . .\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Der Code ist wie folgt zu lesen: Wenn sich der Inhalt der <code>int<\/code>-Variablen <code>i<\/code> auch in einem <code>byte<\/code> darstellen l\u00e4sst, dann matcht die Variable das Pattern und wird im \u201ethen\u201c-Block in der <code>byte<\/code>-Variablen <code>b<\/code> verf\u00fcgbar gemacht. <\/p>\n\n\n\n<p>F\u00fcr beispielsweise <code>a = 50<\/code> w\u00fcrde die Pr\u00fcfung <code>true<\/code> ergeben, f\u00fcr <code>a = 500<\/code> hingegen <code>false<\/code>, da ein <code>byte<\/code> lediglich Werte im Bereich -128 bis +127 speichern kann.<\/p>\n\n\n\n<p>Hier ein zweites Beispiel:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">double<\/span> d = . . .\n<span class=\"hljs-keyword\">if<\/span> (d <span class=\"hljs-keyword\">instanceof<\/span> <span class=\"hljs-keyword\">float<\/span> f) {\n  . . .\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Hier gilt: Wenn sich der Inhalt der <code>double<\/code>-Variablen <code>d<\/code> ohne Pr\u00e4zisionsverlust in einem <code>float<\/code> darstellen l\u00e4sst, dann matcht die Variable das Pattern.<\/p>\n\n\n\n<p>F\u00fcr beispielsweise <code>d = 1.5<\/code> w\u00fcrde die Pr\u00fcfung <code>true<\/code> ergeben, f\u00fcr <code>d = Math.PI<\/code> hingegen <code>false<\/code>, da <code>Math.PI<\/code> (vereinfacht gesagt) mehr Nachkommastellen hat als ein <code>float<\/code> aufnehmen kann.<\/p>\n\n\n\n<p>Auch in switch k\u00f6nnen wir primitive Typ-Pattern verwenden:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">double<\/span> value = ...\n<span class=\"hljs-keyword\">switch<\/span> (value) {\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">byte<\/span>   b -&gt; System.out.println(value + <span class=\"hljs-string\">\" instanceof byte:   \"<\/span> + b);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">short<\/span>  s -&gt; System.out.println(value + <span class=\"hljs-string\">\" instanceof short:  \"<\/span> + s);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">char<\/span>   c -&gt; System.out.println(value + <span class=\"hljs-string\">\" instanceof char:   \"<\/span> + c);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">int<\/span>    i -&gt; System.out.println(value + <span class=\"hljs-string\">\" instanceof int:    \"<\/span> + i);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">long<\/span>   l -&gt; System.out.println(value + <span class=\"hljs-string\">\" instanceof long:   \"<\/span> + l);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">float<\/span>  f -&gt; System.out.println(value + <span class=\"hljs-string\">\" instanceof float:  \"<\/span> + f);\n  <span class=\"hljs-keyword\">case<\/span> <span class=\"hljs-keyword\">double<\/span> d -&gt; System.out.println(value + <span class=\"hljs-string\">\" instanceof double: \"<\/span> + d);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>F\u00fcr <code>value = 5<\/code> w\u00fcrde hier beispielsweise das Pattern <code>byte b<\/code> matchen, f\u00fcr <code>value = 500<\/code> das Pattern <code>short s<\/code>, f\u00fcr <code>value = 5000000<\/code> das Pattern <code>int i<\/code> und f\u00fcr <code>value = 1.5<\/code> das Pattern <code>float f<\/code>.<\/p>\n\n\n\n<p>Auch bei <code>switch<\/code> mit primitiven Typen m\u00fcssen wir das Prinzip der <em>dominierenden<\/em> und <em>dominierten<\/em> Typen sowie die Vollst\u00e4ndigkeitspr\u00fcfung beachten.<\/p>\n\n\n\n<p>Mehr dazu und weitere Beispiele findest du im Hauptartikel <a href=\"https:\/\/www.happycoders.eu\/de\/java\/primitive-type-patterns\/\">Primitive Typen in Patterns, instanceof und switch<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"module-import-declarations-second-preview-jep-494\">Module Import Declarations (Second Preview) \u2013 JEP 494<\/h3>\n\n\n\n<p>Seit jeher k\u00f6nnen wir mit dem <code>import<\/code>-Statement einzelne Klassen oder ganze Pakete importieren.<\/p>\n\n\n\n<p>Mit <code>import module<\/code>, erstmals in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-23-features\/#module-import-declarations-preview-jep-476\">Java 23<\/a> durch <a href=\"https:\/\/openjdk.org\/jeps\/476\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 476<\/a> als Preview-Feature vorgestellt, k\u00f6nnen wir nun auch ganze Module importieren \u2013 und somit alle Klassen, die sich innerhalb des Moduls befinden, direkt verwenden.<\/p>\n\n\n\n<p>Im folgenden Beispiel importieren wir das Modul <code>java.base<\/code> und k\u00f6nnen dadurch die Klassen <code>List<\/code>, <code>Map<\/code>, <code>Stream<\/code> und <code>Collectors<\/code> verwenden, ohne sie einzeln importieren zu m\u00fcssen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-keyword\">module<\/span> java.base;\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> Map&lt;Character, List&lt;String&gt;&gt; groupByFirstLetter(String... values) {\n  <span class=\"hljs-keyword\">return<\/span> Stream.of(values).collect(\n      Collectors.groupingBy(s -&gt; Character.toUpperCase(s.charAt(<span class=\"hljs-number\">0<\/span>))));\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\">Mehrdeutige Klassennamen aufl\u00f6sen<\/h4>\n\n\n\n<p>Wenn ein Klassenname in mehreren importierten Modulen vorkommt, z. B. <code>List<\/code> im Modul <code>java.base<\/code> und im Modul <code>java.desktop<\/code>, dann wei\u00df der Compiler nicht, welche Klasse gemeint ist, wie im folgenden Beispiel:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-keyword\">module<\/span> java.base;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-keyword\">module<\/span> java.desktop;\n\n. . .\nList list = <span class=\"hljs-keyword\">new<\/span> ArrayList();  <span class=\"hljs-comment\">\/\/ Compiler error: \"reference to List is ambiguous\"<\/span>\n. . .<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Diese Mehrdeutigkeit kann durch einen Import der gew\u00fcnschten Klasse aufgel\u00f6st werden:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-keyword\">module<\/span> java.base;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-keyword\">module<\/span> java.desktop;\n\n<span class=\"hljs-keyword\">import<\/span> java.util.List;  <span class=\"hljs-comment\">\/\/ \u27f5 This resolves the ambiguity<\/span>\n\n. . .\nList list = <span class=\"hljs-keyword\">new<\/span> ArrayList();\n. . .<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Was in Java 23 noch nicht m\u00f6glich war und in Java 24 im zweiten Preview dieses Features durch <a href=\"https:\/\/openjdk.org\/jeps\/494\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 494<\/a> hinzugekommen ist, ist die M\u00f6glichkeit, die Mehrdeutigkeit auch durch ein Package-Import aufzul\u00f6sen, und zwar wie folgt:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-keyword\">module<\/span> java.base;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-keyword\">module<\/span> java.desktop;\n\n<span class=\"hljs-keyword\">import<\/span> java.util.*;  <span class=\"hljs-comment\">\/\/ \u27f5 This resolves the ambiguity (since Java 24)<\/span>\n\n. . .\nList list = <span class=\"hljs-keyword\">new<\/span> ArrayList();\n. . .<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\">Transitive Imports<\/h4>\n\n\n\n<p>Wenn ein importiertes Modul ein anderes Modul <em>transitiv<\/em> importiert, dann sind auch alle Klassen der exportierten Pakete des transitiv importierten Moduls ohne explizite Imports nutzbar.<\/p>\n\n\n\n<p>Ein Beispiel dazu findest du im <a href=\"https:\/\/www.happycoders.eu\/de\/java\/module-importieren\/#mehrdeutige-klassennamen\">Hauptartikel \u00fcber Module Imports<\/a>.<\/p>\n\n\n\n<p>Dieses Feature f\u00fchrte in Java 23 zu Verwirrung in der Java-Community:<\/p>\n\n\n\n<p>Durch den Import des Moduls <code>java.se<\/code> (ein Aggregator-Modul, das Abh\u00e4ngigkeiten auf alle Module der Java Standard Edition \u201eJava SE\u201c definiert) wurde das Modul <code>java.base<\/code> nicht mit importiert. Das lag daran, <a href=\"https:\/\/docs.oracle.com\/javase\/specs\/jls\/se23\/html\/jls-7.html#jls-7.7.1\" target=\"_blank\" rel=\"noopener\">dass Java-Module bisher keine transitive Abh\u00e4ngigkeit auf <code>java.base<\/code> definieren durften<\/a>.<\/p>\n\n\n\n<p>Durch <a href=\"https:\/\/openjdk.org\/jeps\/494\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 494<\/a> wird diese Einschr\u00e4nkung in der Sprachspezifikation aufgehoben und die Abh\u00e4ngigkeit von <code>java.se<\/code> auf <code>java.base<\/code> als transitiv markiert, so dass nun durch <code>import module java.se<\/code> auch alle Klassen des <code>java.base<\/code>-Moduls verf\u00fcgbar sind.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Anpassungen an JShell und Simple Source Files<\/h4>\n\n\n\n<p>JShell und <a href=\"#simple-source-files-and-instance-main-methods-fourth-preview-jep-495\">Simple Source Files<\/a> importieren, wenn Preview-Features aktiviert sind, automatisch das <code>java.base<\/code>-Modul.<\/p>\n\n\n\n<p>Weitere Beispiele zur Aufl\u00f6sung mehrdeutiger Klassennamen und zu transitiven Modul-Abh\u00e4ngigkeiten findest du im Hauptartikel <a href=\"https:\/\/www.happycoders.eu\/de\/java\/module-importieren\/\">Module importieren in Java: Module Import Declarations<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"flexible-constructor-bodies-third-preview-jep-492\">Flexible Constructor Bodies (Third Preview) \u2013 JEP 492<\/h3>\n\n\n\n<p>Bisher war es in Java-Konstruktoren nicht erlaubt, Code vor dem Aufruf von <code>super()<\/code> oder <code>this()<\/code> aufzurufen. Wenn wir z. B. vor dem Aufruf von <code>super()<\/code> einen Parameter \u00fcberpr\u00fcfen wollten, dann war das nur \u00fcber einen Aufruf einer statischen Methode innerhalb der Klammern des <code>super<\/code>-Aufrufs m\u00f6glich:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ChildClass<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">SuperClass<\/span> <\/span>{\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">ChildClass<\/span><span class=\"hljs-params\">(String parameter)<\/span> <\/span>{\n    <span class=\"hljs-keyword\">super<\/span>(verifyParameter(parameter));\n  }\n\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">static<\/span> String <span class=\"hljs-title\">verifyParameter<\/span><span class=\"hljs-params\">(String parameter)<\/span> <\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (parameter == <span class=\"hljs-keyword\">null<\/span> || parameter.isEmpty()) {\n      <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> IllegalArgumentException();\n    }\n    <span class=\"hljs-keyword\">return<\/span> parameter;\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Bei mehreren Parametern wird das schnell un\u00fcbersichtlich.<\/p>\n\n\n\n<p>Durch \u201eFlexible Constructor Bodies\u201c \u2013 erstmals in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-22-features\/#statements-before-super-preview-jep-447\">Java 22<\/a> als Preview-Feature unter dem Namen \u201eStatements before super(\u2026)\u201c durch <a href=\"https:\/\/openjdk.org\/jeps\/447\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 447<\/a> vorgestellt \u2013 kann der Code wie folgt umgeschrieben werden:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ChildClass<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">SuperClass<\/span> <\/span>{\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">ChildClass<\/span><span class=\"hljs-params\">(String parameter)<\/span> <\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (parameter == <span class=\"hljs-keyword\">null<\/span> || parameter.isEmpty()) {\n      <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> IllegalArgumentException();\n    }\n    <span class=\"hljs-keyword\">super<\/span>(parameter);\n  }\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Vor dem Aufruf von <code>super(...)<\/code> durfte dadurch lesend und schreibend auf Parameter und Variablen des Konstruktors zugegriffen werden, nicht aber auf die Felder der Klasse.<\/p>\n\n\n\n<p>In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-23-features\/#flexible-constructor-bodies-second-preview-jep-482\">Java 23<\/a> wurde das Feature durch <a href=\"https:\/\/openjdk.org\/jeps\/482\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 482<\/a> in \u201eFlexible Constructor Bodies\u201c umbenannt. Die im vorherigen Absatz genannte Einschr\u00e4nkung wurde dahingehend aufgelockert, dass nun auf Felder der Klasse schreibend zugegriffen werden darf, diese also vor Aufruf des Super-Konstruktors initialisiert werden k\u00f6nnen.<\/p>\n\n\n\n<p>Das ist insbesondere hilfreich in F\u00e4llen, in denen der Super-Konstruktor Methoden aufruft, die in der abgeleiteten Klasse \u00fcberschrieben sind und hier lesend auf Felder zugreifen.<\/p>\n\n\n\n<p>Hier ein Beispiel dazu:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">SuperClass<\/span> <\/span>{\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">SuperClass<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n    logCreation();\n  }\n\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">protected<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">logCreation<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n    System.out.println(<span class=\"hljs-string\">\"SuperClass created\"<\/span>);\n  }\n}\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ChildClass<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">SuperClass<\/span> <\/span>{\n  <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">final<\/span> String parameter;\n\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">ChildClass<\/span><span class=\"hljs-params\">(String parameter)<\/span> <\/span>{\n    <span class=\"hljs-keyword\">this<\/span>.parameter = parameter;\n  }\n\n  <span class=\"hljs-meta\">@Override<\/span>\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">protected<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">logCreation<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n    System.out.println(<span class=\"hljs-string\">\"ChildClass created, parameter = \"<\/span> + parameter);\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Was w\u00fcrde nun die Erzeugung eines neuen <code>ChildClass<\/code>-Objekts z. B. mit <code>new ChildClass(\"foo\")<\/code> ausgeben?<\/p>\n\n\n\n<p>Wir w\u00fcrden vermutlich folgende Ausgabe erwarten:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">ChildClass created, parameter = foo<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Klartext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Tats\u00e4chlich bekommen wir aber Folgendes zu sehen (<code>null<\/code> anstelle von <code>foo<\/code>):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">ChildClass created, parameter = null<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Klartext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Woran liegt das?<\/p>\n\n\n\n<p>Der <code>ChildClass<\/code>-Konstruktor ruft als erstes <code>super()<\/code> auf (dieser Aufruf wird vom Compiler am Anfang des <code>ChildClass<\/code>-Konstruktors eingef\u00fcgt). Daraufhin ruft der <code>SuperClass<\/code>-Konstruktor die <code>logCreation()<\/code>-Methode auf, die durch <code>ChildClass<\/code> \u00fcberschrieben wurde. Allerdings wurde zu diesem Zeitpunkt das Feld <code>parameter<\/code> noch nicht zugewiesen und ist daher noch <code>null<\/code>.<\/p>\n\n\n\n<p>Unabh\u00e4ngig von der Frage, ob wir im Konstruktor \u00fcberhaupt nicht-finale, also \u00fcberschreibbare Methoden aufrufen sollten, k\u00f6nnen wir das Problem in Java 23 beheben, indem wir den <code>ChildClass<\/code>-Konstruktor wie folgt ab\u00e4ndern:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">ChildClass<\/span><span class=\"hljs-params\">(String parameter)<\/span> <\/span>{\n  <span class=\"hljs-keyword\">this<\/span>.parameter = parameter;  <span class=\"hljs-comment\">\/\/ \u27f5 First assign the parameter,<\/span>\n  <span class=\"hljs-keyword\">super<\/span>();                     <span class=\"hljs-comment\">\/\/ \u27f5 then call super()<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Dadurch wird der Super-Konstruktor (und damit auch die <code>logCreation()<\/code>-Methode) erst <em>nach<\/em> der Zuweisung des <code>parameter<\/code>-Felds aufgerufen. Und <code>logCreation()<\/code> wird dementsprechend das initialisierte Feld anzeigen und nicht mehr <code>null<\/code>.<\/p>\n\n\n\n<p>In Java 24 werden \u201eFlexible Constructor Bodies\u201c durch <a href=\"https:\/\/openjdk.org\/jeps\/492\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 492<\/a> ohne \u00c4nderungen wiedervorgelegt \u2013 lediglich die Formulierungen des JEPs wurde etwas \u00fcberarbeitet. Flexible Constructor Bodies werden in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-25-features\/\">Java 25<\/a> finalisiert.<\/p>\n\n\n\n<p>Weitere Use-Cases und Besondernheiten, die es zu beachten gibt, kannst du im Hauptartikel <a href=\"https:\/\/www.happycoders.eu\/de\/java\/flexible-constructor-bodies\/\">Flexible Constructor Bodies in Java: Code vor super() aufrufen<\/a> nachlesen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"structured-concurrency-fourth-preview-jep-499\">Structured Concurrency (Fourth Preview) \u2013 JEP 499<\/h3>\n\n\n\n<p>Structured Concurrency (\u201eStrukturierte Nebenl\u00e4ufigkeit\u201c) ist eine moderne Herangehensweise f\u00fcr die Aufteilung von Aufgaben in kleinere, in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/virtual-threads\/\">virtuellen Threads<\/a> parallel ausf\u00fchrbare Teile innerhalb eines im Quellcode klar erkennbaren Code-Blocks.<\/p>\n\n\n\n<p>Dabei sind Start und Ende aller Teilaufgaben klar ersichtlich, und sobald der Code-Block der strukturierten Nebenl\u00e4ufigkeit verlassen wird, ist sichergestellt, dass alle Threads erfolgreich oder fehlerhaft beendet oder abgebrochen sind und dass der Status aller Teilaufgaben bekannt ist.<\/p>\n\n\n\n<p>Structured-Concurrency-Bl\u00f6cke k\u00f6nnen dabei ineinander verschachtelt werden, wie die folgende Grafik zeigt:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-half_400\"><img decoding=\"async\" width=\"400\" height=\"400\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/jep499-structured-concurrency-400x400.png\" alt=\"JEP 499 Structured Concurrency in Java\" class=\"wp-image-42208\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/jep499-structured-concurrency-400x400.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/jep499-structured-concurrency-224x224.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/jep499-structured-concurrency-336x336.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/jep499-structured-concurrency-504x504.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/jep499-structured-concurrency-672x672.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/jep499-structured-concurrency-600x600.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/12\/jep499-structured-concurrency.png 800w\" sizes=\"(max-width: 400px) 100vw, 400px\" \/><\/figure>\n<\/div>\n\n\n<p>Durch verschiedene Strategien kann dar\u00fcberhinaus festgelegt werden, ob z. B. die erfolgreiche oder fehlerhafte Beendigung einer Teilaufgabe direkt zum Abbruch aller anderen Teilaufgaben und zur erfolgreichen oder fehlerhaften Beendigung der Gesamt-Aufgabe f\u00fchrten soll.<\/p>\n\n\n\n<p>Das folgende Code-Beispiel zeigt, wie eine Anwendung Wetterinformationen aus drei Quellen parallel ausliest und bei der ersten Antwort die anderen Anfragen abbricht und die Antwort zur\u00fcckgibt:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-function\">WeatherResponse <span class=\"hljs-title\">getWeatherFast<\/span><span class=\"hljs-params\">(Location location)<\/span>\n    <span class=\"hljs-keyword\">throws<\/span> InterruptedException, ExecutionException <\/span>{\n  <span class=\"hljs-keyword\">try<\/span> (<span class=\"hljs-keyword\">var<\/span> scope = <span class=\"hljs-keyword\">new<\/span> ShutdownOnSuccess&lt;AddressVerificationResponse&gt;()) {\n    scope.fork(() -&gt; weatherService.readFromStation1(location));\n    scope.fork(() -&gt; weatherService.readFromStation2(location));\n    scope.fork(() -&gt; weatherService.readFromStation3(location));\n\n    scope.join();\n\n    <span class=\"hljs-keyword\">return<\/span> scope.result();\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Ohne Structured Concurrency w\u00fcrde diese Aufgabe deutlich l\u00e4ngeren und komplexeren und dadurch auch fehleranf\u00e4lligeren Code erfordern.<\/p>\n\n\n\n<p>Eine ausf\u00fchrliche Beschreibung und zahlreiche weitere Beispiele findest du im Hauptartikel \u00fcber <a href=\"https:\/\/www.happycoders.eu\/de\/java\/structured-concurrency-structuredtaskscope\/\">Structured Concurrency<\/a>.<\/p>\n\n\n\n<p>Structured Concurrency wurde in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-21-features\/#Structured_Concurrency_Preview_JEP_453\">Java 21<\/a> als Preview-Feature eingef\u00fchrt und in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-22-features\/#structured-concurrency-second-preview-jep-462\">Java 22<\/a> und <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-23-features\/#Structured_Concurrency_Third_Preview_JEP_480\">Java 23<\/a> ohne \u00c4nderungen wiedervorgelegt. In Java 24 wird das Feature durch <a href=\"https:\/\/openjdk.org\/jeps\/499\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 499<\/a> erneut ohne \u00c4nderungen wiedervorgelegt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"scoped-values-fourth-preview-jep-487\">Scoped Values (Fourth Preview) \u2013 JEP 487<\/h3>\n\n\n\n<p>Mit Scoped Values k\u00f6nnen wir Werte an direkte oder indirekte Methodenaufrufe \u00fcbergeben, ohne sie als Methoden-Parameter definieren und ggf. durch eine lange Aufrufkette hindurchschleusen zu m\u00fcssen.<\/p>\n\n\n\n<p>Das klassische Beispiel ist der in einer Web-Anwendung eingeloggte User:<\/p>\n\n\n\n<p>Anstatt ein User-Objekt an alle Methoden innerhalb der Webanwendung als Parameter zu \u00fcbergeben, kann dieses in einem Scoped Value gespeichert werden. Alle Methoden, die innerhalb desselben Request-Bearbeitungs-Threads aufgerufen werden, k\u00f6nnen dann das User-Objekt aus diesem Scoped Value abrufen.<\/p>\n\n\n\n<p>Das kommt dir bekannt vor? <\/p>\n\n\n\n<p>Das liegt daran, dass wir solche Use-Cases bisher mit <code>ThreadLocal<\/code>-Variablen implementiert haben. Scoped Values haben jedoch eine ganze Reihe Vorteile, die ich im <a href=\"https:\/\/www.happycoders.eu\/de\/java\/scoped-values\/\">Hauptartikel \u00fcber Scopes Values<\/a> detailliert beschreibe.<\/p>\n\n\n\n<p>Wie implementiert man nun so ein Scoped Value als Java-Code?<\/p>\n\n\n\n<p>Nachdem wir den User authentifiziert haben, hinterlegen wir diesen mit <code>ScopedValue.where()<\/code> in einem Scoped Value und rufen dann im Kontext dieses Scoped Values mit <code>run()<\/code> den Anwendungscode auf:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-22\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Server<\/span> <\/span>{\n  <span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-keyword\">static<\/span> ScopedValue&lt;User&gt; LOGGED_IN_USER = ScopedValue.newInstance();\n\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">serve<\/span><span class=\"hljs-params\">(Request request)<\/span> <\/span>{\n    . . .\n    User loggedInUser = authenticateUser(request);\n    ScopedValue.where(LOGGED_IN_USER, loggedInUser)\n               .run(() -&gt; restAdapter.processRequest(request));\n    . . .\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Die innerhalb der <code>run()<\/code>-Methode aufgerufene Methode \u2013 und wiederum jede von dieser Methode direkt oder indirekt aufgerufene Methode \u2013 kann nun \u00fcber <code>ScopedValue.get()<\/code> auf das <code>User<\/code>-Objekt zugreifen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-23\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ApplicationService<\/span> <\/span>{\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">doSomethingSmart<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n    User loggedInUser = Server.LOGGED_IN_USER.get();\n    . . .\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Scoped Values wurden erstmals in <a href=\"https:\/\/www.happycoders.eu\/java\/java-21-features\/#Scoped_Values_Preview_JEP_446\">Java 21<\/a> als Preview-Feature vorgestellt.<\/p>\n\n\n\n<p>In <a href=\"https:\/\/www.happycoders.eu\/java\/java-23-features\/#Scoped_Values_Third_Preview_JEP_481\">Java 23<\/a> wurde das generische und funktionale Interface <code>ScopedValue.CallableOp<\/code> eingef\u00fchrt, um Exception-Handling beim Aufruf von <code>ScopedValue.call()<\/code> und <code>ScopedValue.callWhere()<\/code> typsicher \u2013 und damit lesbarer und wartbarer \u2013 zu gestalten.<\/p>\n\n\n\n<p>In Java 24 wurden durch <a href=\"https:\/\/openjdk.org\/jeps\/487\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 487<\/a> die Methoden <code>ScopedValue.callWhere()<\/code> und <code>ScopedValue.runWhere()<\/code> entfernt, um die Schnittstelle komplett \u201efluent\u201c zu gestalten. Diese Convenience-Methoden waren in Java 23 wie folgt definiert:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-24\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> &lt;T, R, X extends Throwable&gt; <span class=\"hljs-function\">R <span class=\"hljs-title\">callWhere<\/span><span class=\"hljs-params\">(\n    ScopedValue&lt;T&gt; key, T value, CallableOp&lt;? extends R, X&gt; op)<\/span> <span class=\"hljs-keyword\">throws<\/span> X <\/span>{\n  <span class=\"hljs-keyword\">return<\/span> where(key, value).call(op);\n}\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> &lt;T&gt; <span class=\"hljs-function\"><span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">runWhere<\/span><span class=\"hljs-params\">(ScopedValue&lt;T&gt; key, T value, Runnable op)<\/span> <\/span>{\n  where(key, value).run(op);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-24\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Statt <code>callWhere()<\/code> bzw. <code>runWhere()<\/code> musst du nun entsprechend <code>where()<\/code> gefolgt von <code>call()<\/code> bzw. <code>run()<\/code> aufrufen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"simple-source-files-and-instance-main-methods-fourth-preview-jep-495\">Simple Source Files and Instance Main Methods (Fourth Preview) \u2013 JEP 495<\/h3>\n\n\n\n<p>Wenn Java-Anf\u00e4ngerInnen ihr erstes Java-Programm schreiben, sieht das meist in etwas so aus:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-25\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">HelloWorld<\/span> <\/span>{\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">(String&#091;] args)<\/span> <\/span>{\n    System.out.println(<span class=\"hljs-string\">\"Hello world!\"<\/span>);\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-25\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Hier werden eine ganze Menge Konzepte auf einmal vermittelt: Klassen, Sichtbarkeitsmodifikatoren, <code>static<\/code>, und (ungenutzte) Methodenargumente. Das kann schnell zu \u00dcberforderung f\u00fchren.<\/p>\n\n\n\n<p>W\u00e4re es nicht sch\u00f6n, wenn wir das gleiche einfach wie folgt ausdr\u00fccken k\u00f6nnten?<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-26\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n  println(<span class=\"hljs-string\">\"Hello world!\"<\/span>);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-26\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Genau das wird durch <em>Simple Source Files and Instance Main Methods<\/em> erm\u00f6glicht!<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ein <em>Simple Source File<\/em> \u2013 also eine <em>einfache Quelldatei<\/em> \u2013 ist eine <em>.java<\/em>-Datei, die keine explizite Klassenangabe enth\u00e4lt. Der Compiler erzeugt stattdessen eine sogenannte <em>implizite<\/em> Klasse.<\/li>\n\n\n\n<li>Eine <em>Instance Main Method<\/em> muss weder <em>public<\/em> noch <em>static<\/em> sein, noch muss sie Parameter haben.<\/li>\n<\/ul>\n\n\n\n<p>Au\u00dferdem wird die neue Klasse <code>java.io.IO<\/code> mit den statischen Methoden <code>print()<\/code>, <code>println()<\/code> und <code>readln()<\/code> eingef\u00fchrt. Diese Klasse liegt im <code>java.base<\/code>-Modul, welches in einfachen Quelldateien automatisch importiert wird (s. Abschnitt <a href=\"#Module_Import_Declarations_Second_Preview_JEP_494\">Module Import Declarations<\/a>). Dadurch kann <code>println()<\/code> ohne vorangestelltes <code>System.out<\/code> und ohne <code>import<\/code>-Statement verwendet werden.<\/p>\n\n\n\n<p>Weitere Einzelheiten und Beispiele sowie zu beachtende Einschr\u00e4nkungen und Regelungen zu \u00fcberladenen <code>main()<\/code>-Methoden findest du im Hauptartikel \u00fcber die <a href=\"https:\/\/www.happycoders.eu\/de\/java\/main-methode\/#compact-source-files-and-instance-main-methods\">Java-main()-Methode<\/a>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Feature-Historie<\/h4>\n\n\n\n<p>Dieses Feature wurde erstmals in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-21-features\/#Unnamed_Classes_and_Instance_Main_Methods_Preview_JEP_445\">Java 21<\/a> als \u201eUnnamed Classes and Instance Main Methods\u201c ver\u00f6ffentlicht. In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-22-features\/#implicitly-declared-classes-and-instance-main-methods-second-preview-jep-463\">Java 22<\/a> wurde dann das Konzept der \u201eimpliziert deklarierten Klasse\u201c eingef\u00fchrt, und in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-23-features\/#implicitly-declared-classes-and-instance-main-methods-third-preview-jep-477\">Java 23<\/a> kam die <code>java.io.IO<\/code>-Klasse hinzu.<\/p>\n\n\n\n<p>In Java 24 wurde schlie\u00dflich durch <a href=\"https:\/\/openjdk.org\/jeps\/495\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 495<\/a> der Begriff \u201eSimple Source Files\u201c eingef\u00fchrt und das Feature in \u201eSimple Source Files and Instance Main Methods\u201c umbenannt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"vector-api-ninth-incubator-jep-489\">Vector API (Ninth Incubator) \u2013 JEP 489<\/h3>\n\n\n\n<p>Die Vector API ist eine neue API, mit der mathematische Vektorrechnungen wie die folgende durchgef\u00fchrt werden k\u00f6nnen:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-half_400\"><img decoding=\"async\" width=\"400\" height=\"91\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-vector-addition-400x91.png\" alt=\"java vector addition\" class=\"wp-image-25531\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-vector-addition-400x91.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-vector-addition-224x51.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-vector-addition-336x76.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-vector-addition-504x115.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-vector-addition-672x153.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-vector-addition-600x137.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/12\/java-vector-addition.png 800w\" sizes=\"(max-width: 400px) 100vw, 400px\" \/><\/figure>\n<\/div>\n\n\n<p>Das besondere an der neuen API ist, dass diese Berechnungen optimiert auf Vektor-Instruktionen moderner CPUs abgebildet werden. Dadurch k\u00f6nnen diese Berechnungen bis zu einer bestimmten Vektor-Gr\u00f6\u00dfe in einem einzigen CPU-Zyklus durchgef\u00fchrt werden.<\/p>\n\n\n\n<p>Die Vector-API wird durch <a href=\"https:\/\/openjdk.org\/jeps\/489\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 489<\/a> zum neuten Mal im Incubator-Stadium vorgestellt. Sie wird so lange ein Incubator-Feature bleiben, bis daf\u00fcr notwendige Funktionen aus <a href=\"https:\/\/openjdk.org\/projects\/valhalla\/\" target=\"_blank\" rel=\"noopener\">Projekt Valhalla<\/a> das Preview-Stadium erreicht haben.<\/p>\n\n\n\n<p>Sobald die Vector-API ebenfalls das Preview-Stadium erreicht, werde ich sie detaillierter beschreiben.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"deprecations-warnungen-loeschungen\">Deprecations, Warnungen, L\u00f6schungen<\/h2>\n\n\n\n<p>Auch in Java 24 werden wieder Funktionalit\u00e4ten als \u201edeprecated\u201d markiert, einige Funktionen f\u00fchren zu Warnungen zur Laufzeit und andere wurden endg\u00fcltig entfernt. Um welche Funktionalit\u00e4ten es sich handelt, erf\u00e4hrst du in den n\u00e4chsten Abschnitten.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"warn-upon-use-of-memory-access-methods-in-sun-misc-unsafe-jep-498\">Warn upon Use of Memory-Access Methods in sun.misc.Unsafe \u2013 JEP 498<\/h3>\n\n\n\n<p>Die in Java 1.4 (also vor \u00fcber 20 Jahren) eingef\u00fchrte <code>sun.misc.Unsafe<\/code>-Klasse war ein m\u00e4chtiges, aber auch gef\u00e4hrliches Werkzeug, um direkt auf den Arbeitsspeicher (sowohl Heap als auch nativen, also nicht durch den Garbage Collector verwalteten Speicher) zuzugreifen.<\/p>\n\n\n\n<p>Diese Klasse sollte eigentlich nie von EntwicklerInnen direkt verwendet werden. Doch zum einen konnte es (durch ein damals noch nicht existierendes Modulsystem) nicht verhindert werden, und zum anderen standen uns keine Alternativen zur Verf\u00fcgung.<\/p>\n\n\n\n<p>Doch heute gibt es diese Alternativen:<\/p>\n\n\n\n<p>Als sicherer Ersatz stehen seit Java 9 <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/22\/docs\/api\/java.base\/java\/lang\/invoke\/VarHandle.html\" target=\"_blank\" rel=\"noopener\">VarHandles<\/a> f\u00fcr den Zugriff auf den Java-Heap und seit Java 22 die <a href=\"\/de\/java\/foreign-function-memory-api\/\">Foreign Function &amp; Memory API<\/a> f\u00fcr den Zugriff auf nativen Speicher zur Verf\u00fcgung.<\/p>\n\n\n\n<p>Deshalb werden die Speicherzugriffsmethoden aus <code>sun.misc.Unsafe<\/code> Schritt f\u00fcr Schritt entfernt:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Im ersten Schritt wurden in <a href=\"\/de\/java\/java-23-features\/#Deprecate_the_Memory-Access_Methods_in_sunmiscUnsafe_for_Removal_JEP_471\">Java 23<\/a> die entsprechenden Methoden als <em>deprecated for removal<\/em> markiert.<\/li>\n\n\n\n<li>In Java 24 wird, durch <a href=\"https:\/\/openjdk.org\/jeps\/498\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 498<\/a> definiert, die Benutzung dieser Methoden zu Warnungen zur Laufzeit f\u00fchren.<\/li>\n\n\n\n<li>Voraussichtlich in Java 26 wird die Benutzung dieser Methoden zu einer <code>UnsupportedOperationException<\/code> f\u00fchren.<\/li>\n\n\n\n<li>Und in einem sp\u00e4teren, noch nicht festgelegten Release werden die Methoden vollst\u00e4ndig entfernt werden.<\/li>\n<\/ol>\n\n\n\n<p>Was bedeutet das f\u00fcr uns?<\/p>\n\n\n\n<p>Wir m\u00fcssen mittelfristig unsere Anwendungen daraufhin \u00fcberpr\u00fcen, ob sie die betroffenen Methoden aus <code>java.misc.Unsafe<\/code> verwenden, und falls ja, auf die sichereren Alternativen <a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/22\/docs\/api\/java.base\/java\/lang\/invoke\/VarHandle.html\" target=\"_blank\" rel=\"noopener\">VarHandles<\/a> und die <a href=\"\/de\/java\/foreign-function-memory-api\/\">Foreign Function &amp; Memory API<\/a> umstellen.<\/p>\n\n\n\n<p>Durch die VM-Einstellung <code>--sun-misc-unsafe-memory-access=allow<\/code> k\u00f6nnen wir die Warnungen in Java 24 deaktivieren. Das empfehle ich aber nicht, da wir die \u00c4nderung fr\u00fcher oder sp\u00e4ter ohnehin durchf\u00fchren m\u00fcssen, wenn wir auf neue Java-Versionen upgraden wollen. Au\u00dferdem wird es mit der n\u00e4chsten Stufe, also voraussichtlich in Java 26, diese Option nicht mehr geben.<\/p>\n\n\n\n<p>Folgende Werte stehen f\u00fcr diese VM-Option <code>--sun-misc-unsafe-memory-access<\/code> zur Verf\u00fcgung:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>allow<\/code> \u2013 schaltet, wie eben erkl\u00e4rt, die Warnungen aus.<\/li>\n\n\n\n<li><code>warn<\/code> \u2013 das ist die Default-Einstellung in Java 24, d. h. die Benutzung der Methoden ist nach wie vor erlaubt, f\u00fchrt aber zu einer Warnung zur Laufzeit beim ersten Aufruf einer solchen Methode.<\/li>\n\n\n\n<li><code>debug<\/code> \u2013 f\u00fchrt bei <em>jedem<\/em> Aufruf (also nicht nur beim ersten) zu Warnungen sowie der Ausgabe eines Stacktraces.<\/li>\n\n\n\n<li><code>deny<\/code> \u2013 f\u00fchrt beim Aufruf einer solchen Mehode zu einer <code>UnsupportedOperationException<\/code>. Dies wird voraussichtlich in in Java 26 die Standardeinstellung sein.<\/li>\n<\/ul>\n\n\n\n<p>Eine vollst\u00e4ndige Liste der betroffenen Methoden findest du \u00fcbrigens im Abschnitt <a href=\"https:\/\/openjdk.org\/jeps\/471#sun-misc-Unsafe-memory-access-methods-and-their-replacements\" target=\"_blank\" rel=\"noopener\">sun.misc.Unsafe memory-access methods and their replacements<\/a> von JEP 471, durch den in Java 23 die Methoden als <em>deprecated<\/em> markiert wurden.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"permanently-disable-the-security-manager-jep-486\">Permanently Disable the Security Manager \u2013 JEP 486<\/h3>\n\n\n\n<p>Der urspr\u00fcnglich f\u00fcr die Absicherung von Java Applets entwickelte \u2013 und f\u00fcr heutige Java-Anwendungen nahezu irrelevante \u201eSecurity Manager\u201d wurde in <a href=\"https:\/\/www.happycoders.eu\/java\/java-17-features\/#Deprecate_the_Security_Manager_for_Removal\">Java 17<\/a> als \u201edeprecated for removal\u201d markiert. Dadurch sollten die Resourcen, die f\u00fcr die Wartung des Security Managers aufgebracht wurden, wichtigeren Projekten zugewiesen werden.<\/p>\n\n\n\n<p>In Java 24 kann der Security Manager nicht mehr aktiviert werden, weder beim Start einer Anwendung noch w\u00e4hrend der Laufzeit. Der Versuch f\u00fchrt zu einer Fehlermeldung.<\/p>\n\n\n\n<p>Die Deaktiverung des Security Managers ist in <a href=\"https:\/\/openjdk.org\/jeps\/486\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 486<\/a> dokumentiert.<\/p>\n\n\n\n<p>In einer zuk\u00fcnftigen Java-Version wird der Security Manager dann vollst\u00e4ndig entfernt werden.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"zgc-remove-the-non-generational-mode-jep-490\">ZGC: Remove the Non-Generational Mode \u2013 JEP 490<\/h3>\n\n\n\n<p>In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-21-features\/#Generational_ZGC_JEP_439\">Java 21<\/a> wurde der \u201eGenerational Mode\u201d f\u00fcr den Z Garbage Collector (ZGC) eingef\u00fchrt. Dieser teilt Objekte in kurzlebige (junge Generation) und langlebige (alte Generation) ein, um dadurch die Speicherbereinigung zu optimieren.<\/p>\n\n\n\n<p>Seit <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-23-features\/#ZGC_Generational_Mode_by_Default_JEP_474\">Java 23<\/a> ist dieser Modus standardm\u00e4\u00dfig aktiviert, wenn ZGC ausgew\u00e4hlt wird. Er konnte allerdings durch die VM-Option <code>-XX:+UseZGC -XX:-ZGenerational<\/code> wieder deaktiviert werden.<\/p>\n\n\n\n<p>Um nicht zwei Modi maintainen zu m\u00fcssen, wird durch <a href=\"https:\/\/openjdk.org\/jeps\/490\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 490<\/a> der \u201eNon-Generational Mode\u201d in Java 24 entfernt.<\/p>\n\n\n\n<p>Die VM-Option <code>-XX:-ZGenerational<\/code> hat keinen Effekt mehr und f\u00fchrt zu einer Warnung. In einer zuk\u00fcnftigen Java-Version wird sie entfernt werden und zu einer Fehlermeldung f\u00fchren.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"remove-the-windows-32-bit-x86-port-jep-479\">Remove the Windows 32-bit x86 Port \u2013 JEP 479<\/h3>\n\n\n\n<p>In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-21-features\/#Deprecate_the_Windows_32-bit_x86_Port_for_Removal_JEP_449\">Java 21<\/a> wurde die 32-Bit-Java-Version f\u00fcr Windows als \u201edeprecated for removal\u201d markiert. Zum einen gab es kaum noch Bedarf f\u00fcr diese Version, zum anderen war die Wartung aufwendig, und z.&nbsp;B. <a href=\"https:\/\/www.happycoders.eu\/de\/java\/virtual-threads\/\">virtuelle Threads<\/a> wurden in dieser Version gar nicht erst implementiert.<\/p>\n\n\n\n<p>Konsequenterweise wird in Java 24 durch <a href=\"https:\/\/openjdk.org\/jeps\/479\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 479<\/a> die 32-Bit-Portierung f\u00fcr Windows vollst\u00e4ndig entfernt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"deprecate-the-32-bit-x86-port-for-removal-jep-501\">Deprecate the 32-bit x86 Port for Removal \u2013 JEP 501<\/h3>\n\n\n\n<p>Mit der Entfernung der 32-Bit-Portierung f\u00fcr Windows (s. vorheriger Abschnitt) ist die 32-Bit-Portierung f\u00fcr Linux die letzte verbleibende 32-Bit-Portierung \u2013 und damit die letzte Portierung, f\u00fcr die die JDK-Entwickler Fallbacks f\u00fcr die 32-Bit-Architektur implementieren m\u00fcssen.<\/p>\n\n\n\n<p>Um diesen Extraaufwand in Zukunft vollst\u00e4ndig zu eliminieren, wird durch <a href=\"https:\/\/openjdk.org\/jeps\/501\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 501<\/a> auch die Linux-32-Bit-Portierung als \u201edeprecated for removal\u201d markiert.<\/p>\n\n\n\n<p>In einer zuk\u00fcnftigen Java-Version wird auch diese Portierung vollst\u00e4ndig entfernt werden.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"sonstige-aenderungen-in-java-24\">Sonstige \u00c4nderungen in Java 24<\/h2>\n\n\n\n<p>Nicht alle Features der neuen Java-Version werden uns im t\u00e4glichen Programmieralltag begegnen. In diesem Kapitel findest du \u00c4nderungen, die nur f\u00fcr spezielle Anwendungsf\u00e4lle relevant sind. Als fortgeschrittener Java-Entwickler solltest du von diesen \u00c4nderungen aber auf jeden Fall wenigstens einmal geh\u00f6rt haben.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"class-file-api-jep-484\">Class-File API \u2013 JEP 484<\/h3>\n\n\n\n<p>Mit der Class-File API enth\u00e4lt Java 24 eine offizielle Schnittstelle, um kompilierten Java-Bytecode (also <em>.class<\/em>-Dateien) aus Java-Code heraus zu lesen und zu schreiben. <\/p>\n\n\n\n<p>Die Class-File API ersetzt das im JDK weit verbreitete Bytecode-Manipulations-Frameworks <a href=\"https:\/\/asm.ow2.io\/\" target=\"_blank\" rel=\"noopener\">ASM<\/a>. Grund f\u00fcr die Eigenentwicklung ist der schnelle JDK-Release-Zyklus sowie die Tatsache, dass ASM der aktuellen Java-Version immer mindestens um eine Version hinterherhinkt, d. h. dass die in einem aktuellen JDK enthaltene ASM-Version maximal mit <em>.class<\/em>-Dateien der <em>vorherigen<\/em> Java-Version umgehen kann.<\/p>\n\n\n\n<p>Mit der Ver\u00f6ffentlichung der Class-File API entf\u00e4llt nun diese zyklische Abh\u00e4ngigkeit, und Java 24 kann nun auch von Java 24 erzeugte <em>.class<\/em>-Dateien inspizieren und modifizieren.<\/p>\n\n\n\n<p>Das Class-File-API wurde in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-22-features\/#Class-File_API_Preview_JEP_457\">Java 22<\/a> erstmals als Preview-Feature vorgestellt und in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-23-features\/#Class-File_API_Second_Preview_JEP_466\">Java 23<\/a> mit kleineren Verbesserungen in eine zweite Preview-Runde geschickt.<\/p>\n\n\n\n<p>In Java 24 wird die neue API durch <a href=\"https:\/\/openjdk.org\/jeps\/484\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 484<\/a> \u2013 noch einmal mit kleineren Verbesserungen \u2013 finalisiert.<\/p>\n\n\n\n<p>Da die meisten Java-EntwicklerInnen nur indirekt \u00fcber Tools mit der Class-File-API arbeiten und diese nie direkt aufrufen werden, verzichte ich an dieser Stelle auf eine detaillierte Beschreibung der Schnittstelle. Falls du jedoch Interesse hast, findest du alle Details in <a href=\"https:\/\/openjdk.org\/jeps\/484\" target=\"_blank\" rel=\"noopener\">JEP 484<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"prepare-to-restrict-the-use-of-jni-jep-472\">Prepare to Restrict the Use of JNI \u2013 JEP 472<\/h3>\n\n\n\n<p>Jegliche Interaktion zwischen Java-Code und nativem Code ist riskant, da sie zu undefiniertem Verhalten und Abst\u00fcrzen f\u00fchren kann (C-Code kann beispielsweise \u00fcber die Grenzen eines Arrays hinaus in den Speicher schreiben). Das gilt sowohl f\u00fcr das Java Native Interface (JNI) als auch die <a href=\"https:\/\/www.happycoders.eu\/de\/java\/foreign-function-memory-api\/\">Foreign Function &amp; Memory API (FFM-API)<\/a>, welche JNI langfristig abl\u00f6sen soll.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Status Quo<\/h4>\n\n\n\n<p>In der FFM-API wurden potentiell gef\u00e4hrliche Methoden von Beginn an als \u201erestricted\u201c eingestuft, und ihre Benutzung musste explizit \u00fcber die VM-Option <code>--enable-native-access<\/code> erlaubt werden. Andernfalls wurde zur Laufzeit eine <code>IllegalCallerException<\/code> ausgel\u00f6st.<\/p>\n\n\n\n<p>Das hei\u00dft nicht, dass von der Verwendung dieser Methoden abgeraten wird, sondern lediglich, dass man sich \u00fcber die Verwendung potentiell gef\u00e4hrlicher Funktionen bewusst sein soll \u2013 und sie dementsprechend explizit erlaubt muss.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Ausweitung auf JNI in Java 24<\/h4>\n\n\n\n<p>Durch <a href=\"https:\/\/openjdk.org\/jeps\/472\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 472<\/a> wird in Java 24 die Verwendung entsprechender JNI-Methoden zu Laufzeit-Warnungen f\u00fchren. Diese Warnungen k\u00f6nnen \u2013 wie bisher die Exceptions bei der FFM-API \u2013 durch die VM-Option <code>--enable-native-access<\/code> verhindert werden.<\/p>\n\n\n\n<p>Wie genau funktioniert <code>--enable-native-access<\/code>?<\/p>\n\n\n\n<p>Du kannst den Zugriff auf nativen Code entweder uneingeschr\u00e4nkt f\u00fcr die gesamte Anwendung erlauben:<\/p>\n\n\n\n<p class=\"has-text-align-center\"><code>java --enable-native-access=ALL-UNNAMED ...<\/code><\/p>\n\n\n\n<p>Oder, besser, du erlaubst nativen Zugriff nur auf bestimmte Module:<\/p>\n\n\n\n<p class=\"has-text-align-center\"><code>java --enable-native-access=MODUL1,MODUL2,MODUL3,... ...<\/code><\/p>\n\n\n\n<p>Bei nicht explizit erlaubtem Zugriff w\u00fcrden sich nun \u2013 ohne weitere Anpassung \u2013 JNI und FFM-API unterschiedlich verhalten: JNI w\u00fcrde eine Warnung ausgeben, die FFM-API w\u00fcrde eine <code>IllegalCallerException<\/code> werfen.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Anpassung der FFM-API<\/h4>\n\n\n\n<p>Aus Konsistenzgr\u00fcnden entschieden sich die JDK Developer, das Verhalten der FFM-API zun\u00e4chst aufzuweichen und die FFM-API standardm\u00e4\u00dfig ebenfalls Warnungen ausgeben zu lassen anstatt Exceptions auszul\u00f6sen.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Konfiguration<\/h4>\n\n\n\n<p>Dieses Verhalten kann angepasst werden \u2013 und zwar f\u00fcr beide APIs einheitlich mit dem Kommandozeilenparameter <code>--illegal-native-access<\/code>. Dieser bietet folgende Optionen:<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><thead><tr><th>VM-Option<\/th><th>Beschreibung<\/th><\/tr><\/thead><tbody><tr><td><code style=\"white-space:nowrap\">--illegal-native-access=allow<\/code><\/td><td>Jeglicher Zugriff auf nativen Code wird erlaubt; es werden keine Warnungen ausgegeben und keine Exceptions geworfen.<\/td><\/tr><tr><td><code style=\"white-space:nowrap\">--illegal-native-access=warn<\/code><\/td><td>Zugriff auf nativen Code ist erlaubt, es werden allerdings Warnungen ausgegeben, sofern der Zugriff nicht explizit mit <code style=\"white-space:nowrap\">--enable-native-access<\/code> erlaubt wurde. Dies ist die Standard-Einstellung in Java 24.<\/td><\/tr><tr><td><code style=\"white-space:nowrap\">--illegal-native-access=deny<\/code><\/td><td>Zugriff auf nativen Code f\u00fchrt zu einer <code>IllegalCallerException<\/code>, sofern der Zugriff nicht explizit mit <code style=\"white-space:nowrap\">--enable-native-access<\/code> erlaubt wurde.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Der Modus <code>deny<\/code> wird in einer zuk\u00fcnftigen Version zur Standard-Einstellung werden; dann werden sowohl JNI als auch FFM-API standardm\u00e4\u00dfig eine <code>IllegalCallerException<\/code> werfen.<\/p>\n\n\n\n<p>In einer sp\u00e4tereren Version wird der <code style=\"white-space:nowrap\">--illegal-native-access<\/code>-Parameter entfernt werden, und es wird nur noch den <code>deny<\/code>-Modus geben.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"quantum-resistant-module-lattice-based-key-encapsulation-mechanism-jep-496\">Quantum-Resistant Module-Lattice-Based Key Encapsulation Mechanism \u2013 JEP 496<\/h3>\n\n\n\n<p>Zuk\u00fcnftige Quantencomputer stellen eine Gefahr f\u00fcr die traditionellen kryptografischen Algorithmen wie RSA und Diffie-Hellman dar. Der Einsatz von ML-KEM (<a href=\"https:\/\/csrc.nist.gov\/pubs\/fips\/203\/final\" target=\"_blank\" rel=\"noopener\">Module-Lattice-Based Key Encapsulation Mechanism<\/a> \u2013 der Link f\u00fchrt zur Beschreibung des Verfahrens auf der Webseite des National Institute of Standards and Technology) soll es in Zukunft erm\u00f6glichen, Schl\u00fcssel auch im Zeitalter von Quantencomputern sicher auszutauschen.<\/p>\n\n\n\n<p>Das folgende Beispiel zeigt, wie...<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>der Empf\u00e4nger ein ML-KEM-Schl\u00fcsselpaar erzeugt, <\/li>\n\n\n\n<li>der Sender durch Schl\u00fcsselkapselung mit dem \u00f6ffentlichen Schl\u00fcssel des Empf\u00e4ngers einen geheimen Sitzungsschl\u00fcssel erzeugt und diesen verkapselt<\/li>\n\n\n\n<li>und der Empf\u00e4nger den Sitzungsschl\u00fcssel wieder entkapselt.<\/li>\n<\/ul>\n\n\n\n<p>Danach k\u00f6nnen Sender und Empf\u00e4nger mit Hilfe des quantensicher \u00fcbertragenen Sitzungsschl\u00fcssels sicher Nachrichten austauschen.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-27\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">()<\/span> <span class=\"hljs-keyword\">throws<\/span> GeneralSecurityException <\/span>{\n  <span class=\"hljs-comment\">\/\/ Step 1 (Receiver): Create a ML-KEM public\/private key pair:<\/span>\n  KeyPairGenerator generator = KeyPairGenerator.getInstance(<span class=\"hljs-string\">\"ML-KEM\"<\/span>);\n  KeyPair keyPair = generator.generateKeyPair();\n\n  PublicKey receiverPublicKey = keyPair.getPublic();\n  PrivateKey receiverPrivateKey = keyPair.getPrivate();\n\n  <span class=\"hljs-comment\">\/\/ Step 2 (Sender, has the receiver's public key):<\/span>\n  <span class=\"hljs-comment\">\/\/ Create a session key and encapsulate it:<\/span>\n  KEM kem = KEM.getInstance(<span class=\"hljs-string\">\"ML-KEM\"<\/span>);\n  KEM.Encapsulator encapsulator = kem.newEncapsulator(receiverPublicKey);\n  KEM.Encapsulated encapsulated = encapsulator.encapsulate();\n\n  SecretKey sessionKey = encapsulated.key();\n  System.out.println(HexFormat.of().formatHex(sessionKey.getEncoded()));\n  \n  <span class=\"hljs-keyword\">byte<\/span>&#091;] keyEncapsulationMessage = encapsulated.encapsulation();\n\n  <span class=\"hljs-comment\">\/\/ Step 3 (Receiver, has the sender's key encapsulation message):<\/span>\n  <span class=\"hljs-comment\">\/\/ Decapsulate the session key:<\/span>\n  KEM kr = KEM.getInstance(<span class=\"hljs-string\">\"ML-KEM\"<\/span>);\n  KEM.Decapsulator decapsulator = kr.newDecapsulator(receiverPrivateKey);\n  \n  SecretKey decapsulatedSessionKey = decapsulator.decapsulate(keyEncapsulationMessage);\n  System.out.println(HexFormat.of().formatHex(decapsulatedSessionKey.getEncoded()));\n\n  <span class=\"hljs-comment\">\/\/ Now sender and receiver can exchange messages<\/span>\n  <span class=\"hljs-comment\">\/\/ using the securely transmitted session key.<\/span>\n  <span class=\"hljs-comment\">\/\/ . . .<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-27\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Wenn ich das Programm bei mir starte, erhalte ich z. B. folgende Ausgabe, die belegt, dass verkapselter und entkapselter Sitzungsschl\u00fcssel \u00fcbereinstimmen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-28\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">7fac6ccf466d3ce0412cb8080280bb3c8cfb2fca630042aee2bf17a213ca82fe\n7fac6ccf466d3ce0412cb8080280bb3c8cfb2fca630042aee2bf17a213ca82fe<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-28\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Klartext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Das Implementierung des quantensicheren ML-KEM-Verfahrens im JDK ist in <a href=\"https:\/\/openjdk.org\/jeps\/496\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 496<\/a> beschrieben. Dort findest du auch weitere Anwendungsbeispiele.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"quantum-resistant-module-lattice-based-digital-signature-algorithm-jep-497\">Quantum-Resistant Module-Lattice-Based Digital Signature Algorithm \u2013 JEP 497<\/h3>\n\n\n\n<p>Analog zu dem im vorherigen Abschnitt beschriebenen ML-KEM-Verfahren wird das ebenfalls quantensichere ML-DSA-Verfahren (<a href=\"https:\/\/csrc.nist.gov\/pubs\/fips\/204\/final\" target=\"_blank\" rel=\"noopener\">Module-Lattice-Based Digital Signature Algorithm<\/a> \u2013 auch dieser Link f\u00fchrt zum National Institute of Standards and Technology) ins JDK aufgenommen.<\/p>\n\n\n\n<p>Das folgende Beispiel zeigt, wie...<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>der Sender ein ML-DSA-Schl\u00fcsselpaar erzeugt,<\/li>\n\n\n\n<li>der Sender seine Nachricht mit seinem privaten Schl\u00fcssel signiert,<\/li>\n\n\n\n<li>und der Empf\u00e4nger die Signatur mit dem \u00f6ffentlichen Schl\u00fcssel des Senders verifiziert.<\/li>\n<\/ul>\n\n\n\n<p>Der Empf\u00e4nger kann somit sicherstellen, dass die Nachricht tats\u00e4chlich vom Sender kommt und nicht unterwegs modifiziert wurde.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-29\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">import<\/span> java.security.Signature;\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">()<\/span> <span class=\"hljs-keyword\">throws<\/span> GeneralSecurityException <\/span>{\n  <span class=\"hljs-comment\">\/\/ Step 1 (Sender): Create a ML-KEM public\/private key pair:<\/span>\n  KeyPairGenerator generator = KeyPairGenerator.getInstance(<span class=\"hljs-string\">\"ML-DSA\"<\/span>);\n  KeyPair keyPair = generator.generateKeyPair();\n\n  PublicKey senderPublicKey = keyPair.getPublic();\n  PrivateKey senderPrivateKey = keyPair.getPrivate();\n\n  <span class=\"hljs-comment\">\/\/ Step 2 (Sender): Sign a message using the private key:<\/span>\n  <span class=\"hljs-keyword\">byte<\/span>&#091;] message = <span class=\"hljs-string\">\"Roses bloom nightly.\"<\/span>.getBytes(StandardCharsets.UTF_8);\n  Signature signer = Signature.getInstance(<span class=\"hljs-string\">\"ML-DSA\"<\/span>);\n  signer.initSign(senderPrivateKey);\n  signer.update(message);\n  <span class=\"hljs-keyword\">byte<\/span>&#091;] signature = signer.sign();\n\n  <span class=\"hljs-comment\">\/\/ Step 3 (Receiver): Verify the message using the sender's public key:<\/span>\n  Signature signatureVerifier = Signature.getInstance(<span class=\"hljs-string\">\"ML-DSA\"<\/span>);\n  signatureVerifier.initVerify(senderPublicKey);\n  signatureVerifier.update(message);\n  <span class=\"hljs-keyword\">boolean<\/span> verified = signatureVerifier.verify(signature);\n  \n  . . .\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-29\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Das Implementierung des quantensicheren ML-DSA-Verfahrens im JDK ist in <a href=\"https:\/\/openjdk.org\/jeps\/497\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 497<\/a> beschrieben.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"linking-run-time-images-without-jmods-jep-493\">Linking Run-Time Images without JMODs \u2013 JEP 493<\/h3>\n\n\n\n<p>Eine JDK-Installation besteht aus zwei Komponenten:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>einem Laufzeit-Image (das ausf\u00fchrbare Java-System) <\/li>\n\n\n\n<li>und einem Satz von Java-Modul-Dateien im <em>jmod<\/em>-Verzeichnis.<\/li>\n<\/ul>\n\n\n\n<p>Die Java-Module sind allerdings auch im Laufzeit-Image enthalten, in der Datei <em>lib\/modules<\/em>.<\/p>\n\n\n\n<p>Warum diese Doppelung?<\/p>\n\n\n\n<p>Die Datei <em>lib\/modules<\/em> wird zur Laufzeit einer Java-Anwendung verwendet; die Modul-Dateien im <em>jmod<\/em>-Verzeichnis werden ben\u00f6tigt, um mit dem <em><a href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/11\/tools\/jlink.html\" target=\"_blank\" rel=\"noopener\">jlink<\/a><\/em>-Tool ein benutzerdefiniertes Laufzeit-Image zu generieren.<\/p>\n\n\n\n<p>Durch <a href=\"https:\/\/openjdk.org\/jeps\/493\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 493<\/a> wird es in Zukunft m\u00f6glich sein, ein JDK <em>ohne<\/em> jmod-Dateien zu erstellen; das <em>jlink<\/em>-Tool wird dann die Modulinformationen aus dem Laufzeit-Image entnehmen.<\/p>\n\n\n\n<p>Dadurch kann die Gr\u00f6\u00dfe eines JDKs um etwa 25 % reduziert werden \u2013 das ist insbesondere im Cloud-Umfeld relevant, wo erh\u00f6hter Speicherbedarf und h\u00f6herer Traffic (durch das \u00dcbertragen der Images) zu h\u00f6heren Kosten f\u00fchrt.<\/p>\n\n\n\n<p>Die neue Option ist standardm\u00e4\u00dfig deaktiviert; die JDK-Anbieter m\u00fcssen sich also bei der Generiereung ihres JDKs proaktiv f\u00fcr diese Option entscheiden.<\/p>\n\n\n\n<p>In einer zuk\u00fcnftigen Java-Version k\u00f6nnte die Option standardm\u00e4\u00dfig aktiviert werden.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"late-barrier-expansion-for-g1-jep-475\">Late Barrier Expansion for G1 \u2013 JEP 475<\/h3>\n\n\n\n<p>Um diesen JEP zu verstehen, muss man zun\u00e4chst einmal wissen, was \u201eBarrier\u201c und \u201eExpansion\u201c bedeuten.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Garbage Collector Barrier <\/h4>\n\n\n\n<p>Im Kontext der Garbage Collection bezeichnet eine \u201eBarrier\u201c ein St\u00fcck Code, das vor und\/oder nach dem Zugriff auf Java-Objekte ausgef\u00fchrt wird. <\/p>\n\n\n\n<p>So wird z. B. \u00fcber Write Barriers protokolliert, welche Referenzen von Objekten der alten Generation auf Objekte der jungen Generation existieren, so dass die junge Generation aufger\u00e4umt werden kann, ohne dabei jedes Mal die alte Generation vollst\u00e4ndig scannen zu m\u00fcssen.<\/p>\n\n\n\n<p>Und wenn der Garbage Collector beim Defragmentieren ein Objekt im Heap verschoben hat, dann sorgt eine Read Barrier daf\u00fcr, dass beim Zugriff auf dieses Objekt der Pointer darauf aktualisiert wird.<\/p>\n\n\n\n<p>Diese Barriers werden beim Laden eines Java-Programms durch die JVM automatisch in den Maschinencode eingef\u00fcgt.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Bytecode Expansion<\/h4>\n\n\n\n<p>Wenn ein Java-Programm kompiliert wird, entsteht daraus zun\u00e4chst Plattform-unabh\u00e4nger Bytecode. Beim Start einer Java-Anwendung wird dieser Bytecode dann in hoch-optimierten Maschinencode umgewandelt. <\/p>\n\n\n\n<p>Zum Beispiel k\u00f6nnen Methoden inlined werden, d. h. der Code innerhalb der Methode wird an jede Stelle kopiert, an der die Methode aufgerufen wird \u2013 das erspart den Overhead des Methodenaufrufs. Zudem k\u00f6nnen Schleifen entrollt werden, d. h. eine Schleife wird durch mehrmalige Wiederholung desselben Maschinencodes ersetzt, um den Overhead der \u00dcberpr\u00fcfung der Abbruchbedingung zu eliminieren.<\/p>\n\n\n\n<p>Aufgrund dieser und anderer Optimierungen belegt der Maschinencode in der Regel mehr Speicher als der Bytecode. Daher wird dieser Vorgang auch als \u201eBytecode Expansion\u201c oder nur \u201eExpansion\u201c bezeichnet.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Barrier Expansion \u2013 Status Quo<\/h4>\n\n\n\n<p>Aktuell arbeitet G1 mit \u201eEarly Barrier Expansion\u201c:<\/p>\n\n\n\n<p>Der Barrier-Code liegt zun\u00e4chst in einer plattformunabh\u00e4ngigen Zwischenstufe zwischen Bytecode und Maschinencode vor, der sogenannten \u201eIntermediate Representation\u201c (IR).<\/p>\n\n\n\n<p>Der Byte-Code der Anwendung wird ebenfalls zun\u00e4chst in die \u201eIntermediate Representation\u201c umgewandelt und dann mit dem Barrier-IR-Code kombiniert.<\/p>\n\n\n\n<p>Danach wird der gesamte IR-Code \u00fcber mehrere Optimierungsstufen in Maschinencode \u00fcbersetzt:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full_800\"><img decoding=\"async\" width=\"800\" height=\"189\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-early-barrier-expansion.v2-800x189.png\" alt=\"Early Barrier Expansion steps (JEP 475)\" class=\"wp-image-41949\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-early-barrier-expansion.v2-800x189.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-early-barrier-expansion.v2-224x53.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-early-barrier-expansion.v2-336x79.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-early-barrier-expansion.v2-504x119.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-early-barrier-expansion.v2-672x159.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-early-barrier-expansion.v2-400x95.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-early-barrier-expansion.v2-600x142.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-early-barrier-expansion.v2-944x223.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-early-barrier-expansion.v2-1200x284.png 1200w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-early-barrier-expansion.v2.png 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/figure>\n<\/div>\n\n\n<p>Das hat zwei Vorteile:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Der Barrier-Code kann, da er in der plattformunabh\u00e4ngigen Intermediate Representation vorliegt, ohne Anpassungen auf allen Plattformen verwendet werden.<\/li>\n\n\n\n<li>Der Compiler kann den kompletten Code optimieren, d. h. die Optimierung des Barrier-Codes kann im Kontext des Anwendungscodes erfolgen.<\/li>\n<\/ul>\n\n\n\n<p>Early Expansion hat allerdings zwei signifikante Nachteile:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Der Compiler muss mehr IR-Code (Anwendungs- <em>und<\/em> Barrier-Code) compilieren.<\/li>\n\n\n\n<li>Die Entwickler des Garbage Collectors k\u00f6nnen nicht vorhersehen, wie der Compiler den Barrier-Code optimiert und potentielle Fehler nur schwer reproduzieren.<\/li>\n<\/ul>\n\n\n\n<p>Die JDK-Entwickler entschieden, dass die Nachteile schwerwiegender sind als die Vorteile und Implementierten daher im Rahmen von <a href=\"https:\/\/openjdk.org\/jeps\/475\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 475<\/a> die \u201eLate Barrier Expansion\u201c.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Late Barrier Expansion<\/h4>\n\n\n\n<p>Bei der \u201eLate Barrier Expansion\u201c wird der Barrier Code nicht als IR-Code implementiert, sondern als bereits optimierter Maschinencode. Und dieser wird erst <em>nach<\/em> der Compilierung und Optimierung des Anwendungscodes in den Maschinencode der Anwendung integriert:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full_800\"><img decoding=\"async\" width=\"800\" height=\"189\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-late-barrier-expansion.v4-800x189.png\" alt=\"Late Barrier Expansion steps (JEP 475)\" class=\"wp-image-41957\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-late-barrier-expansion.v4-800x189.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-late-barrier-expansion.v4-224x53.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-late-barrier-expansion.v4-336x79.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-late-barrier-expansion.v4-504x119.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-late-barrier-expansion.v4-672x159.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-late-barrier-expansion.v4-400x95.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-late-barrier-expansion.v4-600x142.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-late-barrier-expansion.v4-944x223.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-late-barrier-expansion.v4-1200x284.png 1200w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/jep-475-late-barrier-expansion.v4.png 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/figure>\n<\/div>\n\n\n<p>Dadurch, dass der Compiler nun weniger Code optimieren muss, werden Anwendungen nach Messungen der JDK-Entwickler um etwa 10\u201320 % schneller!<\/p>\n\n\n\n<p>Der Z Garbage Collector (ZGC) arbeitet \u00fcbrigens bereits seit seiner Einf\u00fchrung in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-15-features\/#ZGC_A_Scalable_Low-Latency_Garbage_Collector\">Java 15<\/a> mit Late Barrier Expansion.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"deprecate-lockingmode-option-along-with-lm_legacy-and-lm_monitor\">Deprecate LockingMode Option, along with LM_LEGACY and LM_MONITOR<\/h3>\n\n\n\n<p>In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-21-features\/#Implement_Alternative_Fast-Locking_Scheme\">Java 21<\/a> wurde f\u00fcr das Objekt-Monitor-Locking (der Mechanimus zur Sperrung eines kritischen Bereichs f\u00fcr andere Threads) der neue <a href=\"https:\/\/www.happycoders.eu\/de\/java\/object-headers-compressed-class-pointers\/#lightweight-locking\">\u201eLightweight Locking\u201c-Modus<\/a> eingef\u00fchrt. Dieser kann bisher \u00fcber die ebenfalls neu eingef\u00fchrte VM-Option <code>-XX:LockingMode=2<\/code> anstelle des bis dahin standardm\u00e4\u00dfig verwendeten <a href=\"https:\/\/www.happycoders.eu\/de\/java\/object-headers-compressed-class-pointers\/#legacy-stack-locking\">\u201eStack Locking\u201c-Modus<\/a> aktiviert werden.<\/p>\n\n\n\n<p>Es k\u00f6nnen seither folgende Locking-Modi ausgew\u00e4hlt werden:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>-XX:LockingMode=0<\/code> \u2013 Ausschlie\u00dflich schwergewichtige Monitor-Objekte (LM_MONITOR)<\/li>\n\n\n\n<li><code>-XX:LockingMode=1<\/code> \u2013 <em>Stack Locking<\/em> + Monitor-Objekte bei Contention (LM_LEGACY)<\/li>\n\n\n\n<li><code>-XX:LockingMode=2<\/code> \u2013 <em>Lightweight Locking<\/em> + Monitor-Objekte bei Contention (LM_LIGHTWEIGHT)<\/li>\n<\/ul>\n\n\n\n<p>In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-22-features\/#Make_LockingMode_a_product_flag\">Java 22<\/a> wurde die experimentelle Option zu einer produktiven Option bef\u00f6rdert.<\/p>\n\n\n\n<p>In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-23-features\/#Change_LockingMode_default_from_LM_LEGACY_to_LM_LIGHTWEIGHT\">Java 23<\/a> wurde <em>Lightweight Locking<\/em> dann zum neuen Default-Modus.<\/p>\n\n\n\n<p>In Java 24 werden die VM-Option <code>-XX:LockingMode<\/code> sowie die ausw\u00e4hlbaren Modi <code>LM_MONITOR<\/code> und <code>LM_LEGACY<\/code> sowie der <em>Stack-Locking<\/em>-Mechanismus als \u201edeprecated\u201c markiert.<\/p>\n\n\n\n<p>Der Mechanismus \u201eschwergewichtige Monitor-Objekte\u201c selbst ist nicht \u201edeprecated\u201c, sollte aber nicht mehr \u00fcber <code>-XX:LockingMode=0<\/code> ausgew\u00e4hlt werden, sondern \u2013 wie schon vor Java 21 \u2013 \u00fcber die VM-Option <code>-XX:+UseHeavyMonitors<\/code>.<\/p>\n\n\n\n<p>In Java 26 soll <code>-XX:LockingMode<\/code> keinen Effekt mehr haben, und in Java 27 soll die Option vollst\u00e4ndig entfernt werden.<\/p>\n\n\n\n<p><em>(F\u00fcr diese \u00c4nderung gibt es kein JDK Enhancement Proposal; sie ist im Bug Tracker unter <\/em><a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8334299\" target=\"_blank\" rel=\"noopener\">JDK-8334299<\/a><em> beschrieben.)<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"support-fuer-unicode-13-0\">Support f\u00fcr Unicode 16.0<\/h3>\n\n\n\n<p>In Java 24 wird der Unicode-Support auf Version 16.0 angehoben.<\/p>\n\n\n\n<p>Warum ist das relevant?<\/p>\n\n\n\n<p>Alle zeichenverarbeitenden Klassen, wie <code>String<\/code> und <code>Character<\/code>, m\u00fcssen mit den in der neuen Unicode-Version eingef\u00fchrten Zeichen und Codebl\u00f6cken umgehen k\u00f6nnen.<\/p>\n\n\n\n<p>Ein Beispiel findest du im <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-11-features\/#Unicode_10\">Abschnitt Unicode 10<\/a> des Artikels \u00fcber Java 11.<\/p>\n\n\n\n<p><em>(F\u00fcr die Abhebung der Unicode-Version auf 16.0 gibt es kein JDK Enhancement Proposal; die \u00c4nderung ist im Bug-Tracker unter <a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8319993\" target=\"_blank\" rel=\"noopener\">JDK-8319993<\/a> aufgef\u00fchrt.)<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"vollstaendige-liste-aller-aenderungen-in-java-21\">Vollst\u00e4ndige Liste aller \u00c4nderungen in Java 24<\/h3>\n\n\n\n<p>In diesem Artikel habe ich dir alle JDK Enhancement Proposals (JEPs) sowie eine Auswahl weiterer \u00c4nderungen ohne JEP vorgestellt, die in Java 24 umgesetzt wurden. Eine vollst\u00e4ndige Auflistung aller \u00c4nderungen findest du in den <a href=\"https:\/\/www.oracle.com\/java\/technologies\/javase\/24all-relnotes.html\" target=\"_blank\" rel=\"noreferrer noopener\">Java 24 Release Notes<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"fazit\">Fazit<\/h2>\n\n\n\n<p>Wow \u2013 was f\u00fcr ein umfangreiches Release!<\/p>\n\n\n\n<p>Das waren sie also, die 24 JDK Enhancement Proposals und zwei kleinere \u00c4nderungen aus den Release Notes. Hier noch mal eine kurze Zusammenfassung:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Mit der <em>Stream Gatherers API<\/em> k\u00f6nnen wir unsere eigenen, intermedi\u00e4ren Stream-Operationen schreiben.<\/li>\n\n\n\n<li>In virtuellen Threads k\u00f6nnen wir jetzt <code>synchronized<\/code> um blockierende Aufrufe verwenden, ohne dass dadurch der virtuelle Thread an seinen Carrier gepinnt wird.<\/li>\n\n\n\n<li>Mit <em>Ahead-of-Time Class Loading &amp; Linking<\/em>, der logischen Weiterentwicklung von Class Data Sharing, starten Anwendungen (nach Aussage der JDK-Entwickler) um bis zu 42 % schneller.<\/li>\n\n\n\n<li>Mit der <em>Key Derivation Function API<\/em> und den quantensicheren Verschl\u00fcsselungsverfahren ist Java noch sicherer geworden.<\/li>\n\n\n\n<li>Die Gargabe Collectoren Shenandoah und G1 wurden optimiert: Shenandoah hat einen \u201eGenerational Mode\u201c bekommen, und im G1 wurde aus der \u201eEarly Barrier Expansion\u201c eine \u201eLate Barrier Expansion\u201c gemacht. Im ZGC wurde der alte \u201eNon-Generational Mode\u201c entfernt.<\/li>\n\n\n\n<li>Durch <em>Compact Object Headers<\/em> k\u00f6nnen die Header eines jeden Java Objects auf dem Heap um vier Bytes verk\u00fcrzt und damit der Memory Footprint der gesamten Anwendung signifikant reduziert werden.<\/li>\n\n\n\n<li><em>Primitive Type Patterns<\/em>, <em>Flexible Constructor Bodies<\/em>, <em>Structured Concurrency<\/em> und die <em>Vector API<\/em> wurden ohne \u00c4nderungen als Preview- bzw. Incubator-Features wiedervorgelegt. <\/li>\n\n\n\n<li><em>Implicitly Declared Classes and Instance Main Methods<\/em> wurde in <em>Simple Source Files and Instance Main Methods<\/em> umgenannt.<\/li>\n\n\n\n<li>Bei der Verwendung von <code>import module<\/code> k\u00f6nnen wir Mehrdeutigkeiten nun auch mit einem Package-Import aufl\u00f6sen. Und der Import des Moduls <code>java.se<\/code> macht nun auch die Klassen des <code>java.base<\/code>-Moduls ohne weitere Imports verf\u00fcgbar.<\/li>\n\n\n\n<li>Die Convenience-Methoden <code>ScopedValues.runWhere()<\/code> und <code>callWhere()<\/code> wurden im Sinne einer \u201eFluent API\u201c entfernt.<\/li>\n\n\n\n<li>Die Verwendung der Speicherzugriffsmethoden in <code>sun.misc.Unsafe<\/code> f\u00fchrt ab Java 24 zu Laufzeitwarnungen.<\/li>\n\n\n\n<li>Der Security Manager wurde abgeschaltet.<\/li>\n\n\n\n<li>Die 32-Bit-Windows-Version von Java wurde entfernt, und die 32-Bit-Linux-Version wurde als \u201edeprecated\u201c gekennzeichnet.<\/li>\n\n\n\n<li>Die finalisierte <em>Class-File API<\/em> ersetzt das Byte-Code-Manipulations-Framework ASM.<\/li>\n\n\n\n<li>Die Benutzung unsicherer JNI-Methoden f\u00fchrt zu Warnungen, sofern sie nicht beim Programmstart explizit erlaubt wurde.<\/li>\n\n\n\n<li>JDK-Images k\u00f6nnen auch ohne <em>jmod<\/em>-Dateien ausgeliefert werden, was ihre Gr\u00f6\u00dfe um ca. 25 % reduziert.<\/li>\n\n\n\n<li>Die VM-Option <code>-XX:LockingMode<\/code> wurde als \u201edeprecated\u201c markiert.<\/li>\n\n\n\n<li>Der Unicode-Support wird auf Version 16.0 angehoben.<\/li>\n<\/ul>\n\n\n\n<p>Java 24 kannst du <a href=\"https:\/\/jdk.java.net\/24\/\" target=\"_blank\" rel=\"noopener\">hier<\/a> herunterladen. Falls du zuvor eine Preview-Version installiert hattest: du brauchst mindestens Build 26, um alle in diesem Artikel gezeigten Quellcodes compilieren zu k\u00f6nnen.<\/p>\n\n\n\n<p>Welche der neuen Java 24-Features findest du am spannendsten? Welches Feature vermisst du? Teile deine Meinung in den Kommentaren!<\/p>\n<aside><p>Wenn dir der Artikel weitergeholfen hat, w\u00fcrde ich mich sehr \u00fcber eine positive Bewertung auf meinem <a href=\"https:\/\/www.provenexpert.com\/de-de\/sven-woltmann-happycoders-eu\/7smk\/\" target=\"_blank\" rel=\"noopener\">ProvenExpert-Profil<\/a> freuen. Dein Feedback hilft mir, meine Inhalte weiter zu verbessern und motiviert mich, neue informative Artikel zu schreiben.<\/p>\r\n                        <p>\ud83d\udc49 <a href=\"https:\/\/www.provenexpert.com\/de-de\/sven-woltmann-happycoders-eu\/7smk\/\" target=\"_blank\" rel=\"noopener\">Bewertung abgeben<\/a><\/p>\r\n                        <p>Du m\u00f6chtest \u00fcber alle neue Java-Features auf dem Laufenden sein? Dann <a href=\"#\" data-formkit-toggle=\"d8ee997126\">klicke hier<\/a>, um dich f\u00fcr den HappyCoders-Newsletter anzumelden.<\/p>\r\n                        <p>\ud83d\udc49 <a href=\"#\" data-formkit-toggle=\"d8ee997126\">Newsletter-Anmeldung<\/a><\/p><\/aside>","protected":false},"excerpt":{"rendered":"<p>Alle Java 24-Features mit Beispielen: Stream Gatherers, Synchronize Virtual Threads without Pinning, Ahead-of-Time Class Loading &#038; Linking, Compact Object Headers - und mehr!<\/p>\n","protected":false},"author":1,"featured_media":41299,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_seopress_robots_primary_cat":"","_seopress_titles_title":"","_seopress_titles_desc":"Stream Gatherers, No more pinning in Virtual Threads, AoT Class Loading & Linking, Compact Object Headers","_seopress_robots_index":"","_uag_custom_page_level_css":"","_wp_convertkit_post_meta":{"form":"-1","landing_page":"","tag":"0","restrict_content":"0"},"_metis_text_type":"standard","_metis_text_length":59421,"_post_count":0,"footnotes":""},"categories":[64],"tags":[176],"class_list":["post-41295","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-java","tag-java-versionen"],"uagb_featured_image_src":{"full":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/java-24-features.jpg",1770,986,false],"thumbnail":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/java-24-features.jpg",150,84,false],"medium":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/java-24-features.jpg",300,167,false],"medium_large":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/java-24-features.jpg",768,428,false],"large":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/java-24-features.jpg",1024,570,false],"feature_thumb_224":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/java-24-features-224x125.jpg",224,125,true],"feature_thumb_336":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/java-24-features-336x187.jpg",336,187,true],"feature_thumb_504":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/java-24-features-504x281.jpg",504,281,true],"feature_thumb_672":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/java-24-features-672x374.jpg",672,374,true],"half_400":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/java-24-features-400x223.jpg",400,223,true],"half_600":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/java-24-features-600x334.jpg",600,334,true],"full_800":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/java-24-features-800x446.jpg",800,446,true],"full_944":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/java-24-features-944x526.jpg",944,526,true],"full_1200":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/java-24-features-1200x668.jpg",1200,668,true],"wide_1180":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/java-24-features-1180x490.jpg",1180,490,true],"wide_1770":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/java-24-features-1770x735.jpg",1770,735,true],"1536x1536":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/java-24-features.jpg",1536,856,false],"2048x2048":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2024\/11\/java-24-features.jpg",1770,986,false]},"uagb_author_info":{"display_name":"Sven Woltmann","author_link":"https:\/\/www.happycoders.eu\/de\/author\/sven\/"},"uagb_comment_info":0,"uagb_excerpt":"Alle Java 24-Features mit Beispielen: Stream Gatherers, Synchronize Virtual Threads without Pinning, Ahead-of-Time Class Loading & Linking, Compact Object Headers - und mehr!","public_identification_id":"139084cc79ed4c34a000d606384dacbf","private_identification_id":"1ea86e79e7bf415296b0a5ca38bb383d","_links":{"self":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/41295","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/comments?post=41295"}],"version-history":[{"count":11,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/41295\/revisions"}],"predecessor-version":[{"id":56051,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/41295\/revisions\/56051"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/media\/41299"}],"wp:attachment":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/media?parent=41295"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/categories?post=41295"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/tags?post=41295"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}