{"id":51163,"date":"2025-06-05T06:00:00","date_gmt":"2025-06-05T04:00:00","guid":{"rendered":"https:\/\/www.happycoders.eu\/?p=51163"},"modified":"2026-06-12T22:30:48","modified_gmt":"2026-06-12T20:30:48","slug":"java-25-features","status":"publish","type":"post","link":"https:\/\/www.happycoders.eu\/de\/java\/java-25-features\/","title":{"rendered":"Java 25 Features (mit Beispielen)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Java 25 wurde am 16. September 2025 ver\u00f6ffentlicht. Du kannst es <a href=\"https:\/\/jdk.java.net\/25\/\" target=\"_blank\" rel=\"noopener\">hier<\/a> herunterladen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Meine Java-25-Highlights:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Zwei Jahre nach <a href=\"https:\/\/www.happycoders.eu\/de\/java\/virtual-threads\/\">virtuellen Threads<\/a> sind nun auch <a href=\"#scoped-values-jep-506\">Scoped Values<\/a> ein produktives Feature. Mit <em>Scoped Values<\/em> k\u00f6nnen Daten \u00fcber Methodenketten hinweg bereitgestellt werden, ohne sie als Parameter von Methode zu Methode \u00fcbergeben zu m\u00fcssen.<\/li>\n\n\n\n<li><a href=\"#compact-source-files-and-instance-main-methods-jep-512\">Compact Source Files and Instance Main Methods<\/a>: F\u00fcr kleine Test- und Demoprogramme, wie man sie h\u00e4ufig beim Ausprobieren neuer Features schreibt, ist nun keine Klassendeklaration mehr erforderlich, und die Signatur der <code>main()<\/code>-Methode wurde stark vereinfacht: mehr als <code>void main()<\/code> ist nun nicht mehr n\u00f6tig.<\/li>\n\n\n\n<li>Mit <a href=\"#flexible-constructor-bodies-jep-513\">Flexible Constructor Bodies<\/a> d\u00fcrfen wir ab sofort im Konstruktor Code vor dem Aufruf von <code>super()<\/code> oder <code>this()<\/code> ausf\u00fchren. Das erlaubt es z. B. Parameter zu validieren oder zu berechnen, bevor der Super-Konstruktor aufgerufen wird.<\/li>\n\n\n\n<li>Durch <a href=\"#compact-object-headers-jep-519\">Compact Object Headers<\/a> k\u00f6nnen Objekt-Header von 12 auf 8 Byte komprimiert werden. Insbesondere bei Anwendungen mit vielen kleinen Objekten spart das Speicherplatz und verbessert die Performance.<\/li>\n\n\n\n<li>Mit <a href=\"#stable-values-preview-jep-502\">Stable Values<\/a> (aktuell noch im Preview-Stadium) lassen sich Werte threadsicher beim ersten Zugriff darauf initialisieren \u2013 dann gelten sie als Konstanten und k\u00f6nnen durch die JVM wie finale Felder, z. B. durch Constant Folding, optimiert werden.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr alle JEPs und \u00c4nderungen aus den Release Notes 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=\"scoped-values-jep-506\">Scoped Values \u2013 JEP 506<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Mit Java 25 wird das zweite Feature aus \u201eProject Loom\u201c (nach <a href=\"https:\/\/www.happycoders.eu\/de\/java\/virtual-threads\/\">Virtuellen Threads<\/a>) fertiggestellt: Nach mehreren Runden als Incubator- und Preview-Feature wurden nun auch <em>Scoped Values<\/em> finalisiert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Scoped Values bieten eine elegante M\u00f6glichkeit, Daten \u00fcber Methodenketten hinweg verf\u00fcgbar zu machen, ohne sie als Parameter weitergeben zu m\u00fcssen. Typisches Beispiel: In einer Webanwendung wird nach erfolgreicher Authentifizierung der eingeloggte User in einem Scoped Value hinterlegt. Alle nachfolgenden Methoden \u2013 egal wie tief im Call-Stack sie aufgerufen werden \u2013 k\u00f6nnen dann direkt auf dieses User-Objekt zugreifen:<\/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-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\">static<\/span> <span class=\"hljs-keyword\">final<\/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        User loggedInUser = authenticateUser(request);\n        ScopedValue.where(LOGGED_IN_USER, loggedInUser)\n                .run(() -&gt; restAdapter.processRequest(request));\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 class=\"wp-block-paragraph\">Innerhalb des Aufrufs von <code>restAdapter.processRequest(...)<\/code> kann der eingeloggte User jederzeit \u00fcber <code>LOGGED_IN_USER.get()<\/code> abgerufen werden \u2013 ganz ohne explizite \u00dcbergabe als Parameter. Der Mechanismus erinnert an <code>ThreadLocal<\/code>, hat aber mehrere Vorteile:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Begrenzter G\u00fcltigkeitsbereich:<\/strong> Der Scope ist klar abgegrenzt und endet automatisch mit dem Ablauf von <code>run()<\/code> oder <code>call()<\/code>.<\/li>\n\n\n\n<li><strong>Immutability:<\/strong> Der gespeicherte Wert kann \u2013 im Gegensatz zu <code>ThreadLocal<\/code> \u2013 nicht ver\u00e4ndert werden, was Race Conditions und unerwartete Seiteneffekte verhindert.<\/li>\n\n\n\n<li><strong>Niedrigerer Memory Footprint:<\/strong> Bei der Verwendung von <code>InheritableThreadLocal<\/code> werden Werte in Kind-Threads kopiert, damit \u00c4nderungen im Kind-Thread nicht den Eltern-Thread beeinflussen. Aufgrund der Immutability ist es bei Scoped Value nicht erforderlich, Werte zu kopieren.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Scoped Values wurden erstmals in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-20-features\/#scoped-values-incubator-jep-429\">Java 20<\/a> als Incubator-Feature vorgestellt. Mit <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-23-features\/#scoped-values-third-preview-jep-481\">Java 23<\/a> wurden sie um das generische Interface <code>ScopedValue.CallableOp<\/code> erweitert, das typsicheres Exception-Handling erm\u00f6glicht. In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-24-features\/#scoped-values-fourth-preview-jep-487\">Java 24<\/a> sind die Convenience-Methoden <code>callWhere()<\/code> und <code>runWhere()<\/code> entfernt worden \u2013 zugunsten eines konsistenteren, fluenten Stils:<\/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-comment\">\/\/ Before Java 24:<\/span>\nResult result = ScopedValue.callWhere(LOGGED_IN_USER, loggedInUser, \n                                      () -&gt; doSomethingSmart());\n\n<span class=\"hljs-comment\">\/\/ Since Java 24:<\/span>\nResult result = ScopedValue.where(LOGGED_IN_USER, loggedInUser)\n                           .call(() -&gt; doSomethingSmart());<\/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 class=\"wp-block-paragraph\">In Java 25 werden Scoped Values durch <a href=\"https:\/\/openjdk.org\/jeps\/506\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 506<\/a> finalisiert und k\u00f6nnen somit in Produktionscode eingesetzt werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wenn du bisher <code>ThreadLocal<\/code> genutzt hast, lohnt sich ein Blick auf die neuen M\u00f6glichkeiten. Scoped Values bieten nicht nur bessere Lesbarkeit und Wartbarkeit, sondern passen auch perfekt zur neuen Welt der virtuellen Threads.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud83d\udc49 Eine ausf\u00fchrliche Einf\u00fchrung findest du im <a href=\"https:\/\/www.happycoders.eu\/de\/java\/scoped-values\/\">Hauptartikel \u00fcber Scoped Values<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"module-import-declarations-jep-511\">Module Import Declarations \u2013 JEP 511<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Nach zwei Runden als Preview in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-23-features\/#module-import-declarations-preview-jep-476\">Java 23<\/a> und <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-24-features\/#module-import-declarations-second-preview-jep-494\">Java 24<\/a> wurden in Java 25 durch <a href=\"https:\/\/openjdk.org\/jeps\/511\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 511<\/a> auch <em>Module Import Declarations<\/em> finalisiert \u2013 ohne weitere \u00c4nderungen.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Was macht <code>import module<\/code>?<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Seit Java 1.0 werden Klassen aus dem Paket <code>java.lang<\/code> automatisch verf\u00fcgbar gemacht. Auch ganze Pakete konnten wir schon immer mit dem <code>import<\/code>-Statement einbinden. Was lange nicht m\u00f6glich war: der Import ganzer Module. Genau das macht nun <code>import module<\/code> m\u00f6glich.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ein Modul-Import erm\u00f6glicht es dir, alle Klassen aus den exportierten Paketen eines Moduls zu verwenden:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" 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-4\"><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 class=\"wp-block-paragraph\">Im Beispiel oben musst du weder <code>java.util.List<\/code> noch <code>java.util.stream.Collectors<\/code> einzeln importieren \u2013 sie geh\u00f6ren alle zum <code>java.base<\/code>-Modul.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wichtig: Du brauchst daf\u00fcr keine <code>module-info.java<\/code>. Auch klassische Projekte ohne Module profitieren vom neuen Mechanismus.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Namenskonflikte bei mehrfach vorkommenden Klassen<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Wenn zwei importierte Module eine Klasse mit identischem Namen bereitstellen, kann der Compiler nicht ohne weiteres wissen, welche ben\u00f6tigt wird. Ein Beispiel ist die Klasse <code>Date<\/code> \u2013 sie ist sowohl in <code>java.base<\/code> als auch in <code>java.sql<\/code> enthalten:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" 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.sql;\n\n<span class=\"hljs-comment\">\/\/ . . .<\/span>\n\nDate date = <span class=\"hljs-keyword\">new<\/span> Date();  <span class=\"hljs-comment\">\/\/ Compilerfehler: \"reference to Date is ambiguous\"<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><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 class=\"wp-block-paragraph\">Die L\u00f6sung? Du gibst durch einen expliziten Klassennamen-Import an, welche Variante du nutzen m\u00f6chtest:<\/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\">import<\/span> <span class=\"hljs-keyword\">module<\/span> java.base;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-keyword\">module<\/span> java.sql;\n<span class=\"hljs-keyword\">import<\/span> java.util.Date;  <span class=\"hljs-comment\">\/\/ \u27f5 Das l\u00f6st die Mehrdeutigkeit auf<\/span>\n\n<span class=\"hljs-comment\">\/\/ . . .<\/span>\n\nDate date = <span class=\"hljs-keyword\">new<\/span> Date();<\/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 class=\"wp-block-paragraph\">Seit Java 24 kannst du solche Konflikte auch durch Paket-Importe aufl\u00f6sen:<\/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\">import<\/span> <span class=\"hljs-keyword\">module<\/span> java.base;\n<span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-keyword\">module<\/span> java.sql;\n<span class=\"hljs-keyword\">import<\/span> java.util.*; <span class=\"hljs-comment\">\/\/ \u27f5 Auch das l\u00f6st die Mehrdeutigkeit auf<\/span>\n\n<span class=\"hljs-comment\">\/\/ . . .<\/span>\n\nDate date = <span class=\"hljs-keyword\">new<\/span> Date();<\/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<h4 class=\"wp-block-heading\">Transitive Modul-Abh\u00e4ngigkeiten<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Ein gro\u00dfer Vorteil von <code>import module<\/code> liegt in der Unterst\u00fctzung transitiver Abh\u00e4ngigkeiten: Wenn ein Modul ein anderes transitiv einbindet, sind dessen exportierte Pakete ebenfalls verf\u00fcgbar \u2013 ganz ohne zus\u00e4tzlichen Import.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Beispiel: <code>java.sql<\/code> deklariert eine transitive Abh\u00e4ngigkeit auf <code>java.xml<\/code>:<\/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\">module<\/span> java.sql {\n    <span class=\"hljs-keyword\">requires<\/span> transitive java.xml;\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 class=\"wp-block-paragraph\">Dadurch kannst du direkt Klassen wie <code>SAXParserFactory<\/code> verwenden, ohne <code>java.xml<\/code> explizit zu importieren:<\/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\">import<\/span> <span class=\"hljs-keyword\">module<\/span> java.sql;\n\nSAXParserFactory factory = SAXParserFactory.newInstance();<\/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 class=\"wp-block-paragraph\">Neu in Java 24 (und damit jetzt auch final in Java 25) ist, dass <code>java.base<\/code> ebenfalls als transitive Abh\u00e4ngigkeit funktioniert \u2013 etwa wenn du <code>java.se<\/code> importierst, das <code>java.base<\/code> zuvor nicht transitiv eingebunden hatte.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Auswirkungen auf JShell und Compact Source Files<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">JShell und die sogenannten <a href=\"#compact-source-files-and-instance-main-methods-jep-512\">Compact Source Files<\/a>, die ebenfalls in Java 25 finalisiert und im n\u00e4chsten Abschnitt beschrieben werden, importieren nun automatisch <code>java.base<\/code>. Das reduziert Boilerplate-Code in interaktiven Sessions und in kompakten Quelldateien.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud83d\udc49 Weitere Hintergr\u00fcnde, praktische Beispiele und tiefergehende Erkl\u00e4rungen findest du im <a href=\"https:\/\/www.happycoders.eu\/de\/java\/module-importieren\/\">Hauptartikel \u00fcber Module Import Declarations<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"compact-source-files-and-instance-main-methods-jep-512\">Compact Source Files and Instance Main Methods \u2013 JEP 512<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Wenn Java-Anf\u00e4nger:innen ihr erstes Programm schreiben, sieht das h\u00e4ufig so aus:<\/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\">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-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 class=\"wp-block-paragraph\">F\u00fcr erfahrene Entwickler:innen mag das vollkommen selbstverst\u00e4ndlich sein \u2013 doch Einsteiger:innen werden durch Sichtbarkeitsmodifikatoren wie <code>public<\/code>, Klassen, statische Methoden, ein ungenutztes <code>args<\/code>-Array und ein etwas sperriges <code>System.out<\/code> \u00fcberfordert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Mit Java 25 wird all das optional. <em>Compact Source Files and Instance Main Methods<\/em> \u2013 nach vier Preview-Runden mit variierenden Feature-Namen durch <a href=\"https:\/\/openjdk.org\/jeps\/512\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 512<\/a> finalisiert \u2013 erm\u00f6glicht kompakte Java-Programme ohne explizite Klassenstruktur:<\/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-function\"><span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n    IO.println(<span class=\"hljs-string\">\"Hello world!\"<\/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\">Funktionsweise im Detail<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Ein Compact Source File ist eine <code>.java<\/code>-Datei, die keine explizite Klassen- oder Paketdeklaration enth\u00e4lt. Der Java-Compiler erzeugt beim \u00dcbersetzen automatisch eine sogenannte implizit deklarierte Klasse. Diese Klasse ist nicht sichtbar und nicht durch andere Klassen referenzierbar.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die <code>main()<\/code>-Methode \u2013 egal ob in herk\u00f6mmlichen oder kompakten Quelldateien \u2013 muss nicht mehr <code>static<\/code> oder <code>public<\/code> sein, und auch der <code>args<\/code>-Parameter ist optional. Wenn die Methode nicht statisch ist, es sich also um eine Instanzmethode handelt, wird beim Programmstart automatisch eine Instanz der Klasse erzeugt und die <code>main()<\/code>-Methode dieser Instanz aufgerufen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die neue Klasse <code>IO<\/code> stellt mit <code>print()<\/code>, <code>println()<\/code> und <code>readln()<\/code> die drei wichtigsten Ein- und Ausgabemethoden zur Verf\u00fcgung. Sie liegt im Paket <code>java.lang<\/code> und ist damit automatisch in allen Java-Dateien ohne <code>import<\/code>-Statement verf\u00fcgbar.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In kompakten Quelldateien wird das Modul <code>java.base<\/code> automatisch importiert. Damit stehen alle Klassen der von diesem Modul exportierten Pakete unmittelbar (also ohne Imports) zur Verf\u00fcgung. Mehr Informationen zu Modul-Imports findest du im Abschnitt <a href=\"#module-import-declarations-jep-511\">Module Import Declarations<\/a>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Warum ist das wichtig?<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Durch diese Neuerungen wird der Einstieg in Java sp\u00fcrbar einfacher. Kompakte Programme wie dieses lassen sich direkt ausf\u00fchren:<\/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-function\"><span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">main<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n    IO.println(greet(<span class=\"hljs-string\">\"world\"<\/span>));\n}\n\n<span class=\"hljs-function\">String <span class=\"hljs-title\">greet<\/span><span class=\"hljs-params\">(String name)<\/span> <\/span>{\n    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-string\">\"Hello \"<\/span> + name + <span class=\"hljs-string\">\"!\"<\/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 class=\"wp-block-paragraph\">Die volle Ausdruckskraft der Sprache bleibt erhalten, nur eben mit deutlich geringerem syntaktischem Overhead. Klassen, Modifier, Pakete, Module k\u00f6nnen dann eingef\u00fchrt werden, wenn sie gebraucht werden \u2013 sobald die Programme gr\u00f6\u00dfer werden und mehr Struktur erfordern.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">R\u00fcckblick<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-21-features\/#unnamed-classes-and-instance-main-methods-preview-jep-445\">Java 21<\/a> wurde das Feature unter dem Namen <em>Unnamed Classes and Instance Main Methods<\/em> erstmals vorgestellt. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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 das Konzept der \u201eunbenannten Klassen\u201c durch \u201eimplizit deklarierte Klassen\u201c ersetzt. Gleichzeitig wurde das Launch-Protokoll vereinfacht, das steuert, welche <code>main()<\/code>-Methode ausgef\u00fchrt wird, falls mehrere <code>main()<\/code>-Methoden existieren.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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> wurde die <code>java.io.IO<\/code>-Hilfsklasse eingef\u00fchrt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-24-features\/#simple-source-files-and-instance-main-methods-fourth-preview-jep-495\">Java 24<\/a> wurde das Feature \u2013 ohne sonstige \u00c4nderungen \u2013 in <em>Simple Source Files and Instance Main Methods<\/em> umbenannt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In Java 25 wurde das Feature durch <a href=\"https:\/\/openjdk.org\/jeps\/512\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 512<\/a> finalisiert und ein letztes Mal umbenannt \u2013 in <em>Compact Source Files and Instance Main Methods<\/em>. Die <code>IO<\/code>-Klasse, die sich zuvor im Paket <code>java.io<\/code> befand und deren Methoden automatisch statisch importiert wurden, wandert ins Paket <code>java.lang<\/code>, und ihre Methoden m\u00fcssen explizit importiert werden. Somit gibt es keine Sonderregelung mehr f\u00fcr diese eine Klasse.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud83d\udc49 Weitere Details zur <code>main()<\/code>-Methode, dem \u201eLaunch-Protokoll\u201c und Spezialf\u00e4llen findest du im Abschnitt <a href=\"https:\/\/www.happycoders.eu\/de\/java\/main-methode\/#compact-source-files-and-instance-main-methods\">Compact Source Files and Instance Main Method<\/a> im Artikel \u00fcber die <code>main()<\/code>-Methode.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"flexible-constructor-bodies-jep-513\">Flexible Constructor Bodies \u2013 JEP 513<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Konstruktoren in Java waren lange in ihrer Struktur streng limitiert: Vor dem Aufruf von <code>super(\u2026)<\/code> oder <code>this(\u2026)<\/code> durfte kein eigener Code stehen. Dadurch entstanden immer wieder teils umst\u00e4ndliche Konstruktionen \u2013 besonders dann, wenn man Parameter validieren oder vorberechnen wollte.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Das Problem bisher: Umst\u00e4ndliche Konstruktor-Logik<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Ein Beispiel macht das deutlich:<\/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\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Square<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Rectangle<\/span> <\/span>{\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">Square<\/span><span class=\"hljs-params\">(Color color, <span class=\"hljs-keyword\">int<\/span> area)<\/span> <\/span>{\n        <span class=\"hljs-keyword\">this<\/span>(color, Math.sqrt(validateArea(area)));\n    }\n\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">static<\/span> <span class=\"hljs-keyword\">double<\/span> <span class=\"hljs-title\">validateArea<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> area)<\/span> <\/span>{\n        <span class=\"hljs-keyword\">if<\/span> (area &lt; <span class=\"hljs-number\">0<\/span>) <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> IllegalArgumentException();\n        <span class=\"hljs-keyword\">return<\/span> area;\n    }\n\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-title\">Square<\/span><span class=\"hljs-params\">(Color color, <span class=\"hljs-keyword\">double<\/span> sideLength)<\/span> <\/span>{\n        <span class=\"hljs-keyword\">super<\/span>(color, sideLength, sideLength);\n    }\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 class=\"wp-block-paragraph\">Hier muss die Validierung in eine separate Methode und die Umrechnung der Fl\u00e4che in eine Seitenl\u00e4nge in einen separaten Konstruktor ausgelagert werden. Warum? Weil (bisher) <code>super(\u2026)<\/code> immer das erste Statement im Konstruktor sein musste.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Das macht den Code unn\u00f6tig komplex und schwer lesbar \u2013 wie dir sicher beim ersten Blick auf den Code aufgefallen ist ;-)<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Flexible Konstruktoren in Java 25<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Seit Java 25 geh\u00f6rt dieses Anti-Pattern der Vergangenheit an \u2013 dank den durch <a href=\"https:\/\/openjdk.org\/jeps\/513\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 513<\/a> finalisierten \u201eFlexible Constructor Bodies\u201c.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ab sofort gilt: Vor dem Aufruf von <code>super(\u2026)<\/code> oder <code>this(\u2026)<\/code> darf beliebiger Code stehen \u2013 solange er nicht lesend auf noch nicht initialisierte Instanzfelder zugreift.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Das bedeutet:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Du kannst Parameter validieren.<\/li>\n\n\n\n<li>Du kannst lokale Variablen berechnen.<\/li>\n\n\n\n<li>Du darfst sogar Felder initialisieren \u2013 und das ist besonders hilfreich, wenn der Super-Konstruktor Methoden aufruft, die in der Subklasse \u00fcberschrieben wurden.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Das f\u00fchrt zu deutlich lesbarerem Code:<\/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\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Square<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Rectangle<\/span> <\/span>{\n    <span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-title\">Square<\/span><span class=\"hljs-params\">(Color color, <span class=\"hljs-keyword\">int<\/span> area)<\/span> <\/span>{\n        <span class=\"hljs-keyword\">if<\/span> (area &lt; <span class=\"hljs-number\">0<\/span>) <span class=\"hljs-keyword\">throw<\/span> <span class=\"hljs-keyword\">new<\/span> IllegalArgumentException();\n        <span class=\"hljs-keyword\">double<\/span> sideLength = Math.sqrt(area);\n        <span class=\"hljs-keyword\">super<\/span>(color, sideLength, sideLength);\n    }\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<p class=\"wp-block-paragraph\">Hier ist auf den ersten Blick ersichtlich, was passiert:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Die Fl\u00e4che wird validiert.<\/li>\n\n\n\n<li>Die Seitenl\u00e4nge wird berechnet.<\/li>\n\n\n\n<li>Der <code>Rectangle<\/code>-Konstruktor wird aufgerufen.<\/li>\n<\/ol>\n\n\n\n<h4 class=\"wp-block-heading\">Weniger \u00dcberraschungen bei Vererbung<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Ein h\u00e4ufig untersch\u00e4tztes Problem war bisher auch das folgende:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wird im Super-Konstruktor eine Methode aufgerufen, die in der Subklasse \u00fcberschrieben ist und die dort auf Felder der Subklasse zugreift, kann das zu \u00dcberraschungen f\u00fchren.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Hier ein Beispiel:<\/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\">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();  <span class=\"hljs-comment\">\/\/ \u27f5 2.<\/span>\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>);  <span class=\"hljs-comment\">\/\/ \u27f5 not invoked; <\/span>\n                                                   <span class=\"hljs-comment\">\/\/ method is overridden in ChildClass<\/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\">super<\/span>();                     <span class=\"hljs-comment\">\/\/ \u27f5 1.<\/span>\n        <span class=\"hljs-keyword\">this<\/span>.parameter = parameter;  <span class=\"hljs-comment\">\/\/ \u27f5 4.<\/span>\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\">\"parameter = \"<\/span> + parameter);  <span class=\"hljs-comment\">\/\/ \u27f5 3.<\/span>\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 class=\"wp-block-paragraph\">Ein Aufruf von <code>new ChildClass(\"foo\")<\/code> w\u00fcrde nicht etwa \u201eSuperClass created\u201c ausgeben oder \u201eparameter = foo\u201c. Nein, dieser Aufruf w\u00fcrde Folgendes ausgeben:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">parameter = null<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><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 class=\"wp-block-paragraph\">Der Grund: <code>parameter<\/code> wird erst in Schritt 4 (s. Quellcode-Kommentare) \u2013 also <em>nach<\/em> dem Aufruf des Super-Konstruktors \u2013 gesetzt. Die vom Super-Konstruktor aufgerufene, durch <code>ChildClass<\/code> \u00fcberschriebene Methode <code>logCreation()<\/code> greift daher in Schritt 3 auf ein noch nicht initialisiertes Feld zu.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Mit <em>Flexible Constructor Bodies<\/em> l\u00e4sst sich das ganz einfach verhindern:<\/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-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    <span class=\"hljs-keyword\">super<\/span>();\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 class=\"wp-block-paragraph\">Wir d\u00fcrfen Felder nun zuweisen, <em>bevor<\/em> wir den Super-Konstruktor aufrufen.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">R\u00fcckblick<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Flexible Constructor Bodies starteten in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-22-features\/#statements-before-super-preview-jep-447\">Java 22<\/a> unter dem Namen \u201eStatements before super(\u2026)\u201c.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-23-features\/#flexible-constructor-bodies-second-preview-jep-482\">Java 23<\/a> erhielten sie den aktuellen Namen, und es kam die M\u00f6glichkeit hinzu Felder vor dem Aufruf des Super-Konstruktors zu initialisieren.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-24-features\/#flexible-constructor-bodies-third-preview-jep-492\">Java 24<\/a> wurde das Feature ohne \u00c4nderungen wiedervorgelegt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Im Java 25 werden sie durch <a href=\"https:\/\/openjdk.org\/jeps\/513\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 513<\/a> ohne \u00c4nderungen finalisiert und k\u00f6nnen damit in Produktionscode eingesetzt werden. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\ud83d\udc49 Weitere Anwendungsf\u00e4lle, Details und Besonderheiten findest du im Hauptartikel: <a class=\"\" href=\"https:\/\/www.happycoders.eu\/de\/java\/flexible-constructor-bodies\/\">Flexible Constructor Bodies in Java: Code vor super() aufrufen<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"performance-verbesserungen\">Performance-Verbesserungen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Java 25 bringt Performance-Verbesserungen in verschiedenen Bereichen der JVM: Durch Compact Object Headers wird der Speicherverbrauch effizienter gestaltet; durch den Generational Shenandoah wird die Garbage Collection optimiert. Hinzu kommen zwei Erweiterungen zum in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-24-features\/#ahead-of-time-class-loading-linking-jep-483\">Java 24<\/a> ver\u00f6ffentlichten <a href=\"https:\/\/www.happycoders.eu\/de\/java\/ahead-of-time-class-loading-and-linking\/\">Ahead-of-Time Class Loading and Linking<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"compact-object-headers-jep-519\">Compact Object Headers \u2013 JEP 519<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Jedes Java-Objekt enth\u00e4lt neben den eigentlichen Datenfeldern auch einen <a href=\"https:\/\/www.happycoders.eu\/de\/java\/object-headers-compressed-class-pointers\/\">Objekt-Header<\/a>. Dieser enth\u00e4lt Metainformationen wie den Hash-Code des Objekts, Sperrinformationen (f\u00fcr Synchronisation), das Objektalter (f\u00fcr die Garbage Collection) und einen Zeiger auf die Klassendatenstruktur.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bisher war dieser Header in der Regel 12 Byte gro\u00df \u2013 bei ausgeschalteten <a href=\"https:\/\/www.happycoders.eu\/de\/java\/object-headers-compressed-class-pointers\/#compressed-class-pointers\">Compressed Class Pointers<\/a> sogar 16 Byte.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Innerhalb von <a href=\"https:\/\/wiki.openjdk.org\/spaces\/lilliput\/overview\" target=\"_blank\" rel=\"noopener\">Project Lilliput<\/a> ist es den JDK-Entwickler:innen gelungen, den Header auf 8 Byte zu verkleinern \u2013 ohne dabei Funktionalit\u00e4t einzub\u00fc\u00dfen. Diese kompaktere Variante nennt sich <em>Compact Object Header<\/em> und spart erheblich Speicher, insbesondere bei einer gro\u00dfen Anzahl an Objekten.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Aufbau des bisherigen 12-Byte-Objekt-Headers<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">So sieht der 12-Byte-Header bisher aus:<\/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=\"Java Object Header: Mark Word und 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 class=\"wp-block-paragraph\">Der 12-Byte-Header besteht aus:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>einem <em>Mark Word<\/em>, das den Identity Hash Code des Objekts enth\u00e4lt, dessen Alter und zwei sogenannte Tag Bits (f\u00fcr die Synchronisation)<\/li>\n\n\n\n<li>und einem <em>Class Word<\/em> mit einem komprimierten Pointer auf die Klassendatenstruktur.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Aufbau des \u201ekompakten\u201c 8-Byte-Objekt-Headers<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Und so ist der neue 8-Byte-Header aufgebaut (Hinweis: Ma\u00dfstab ge\u00e4ndert):<\/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=\"Aufbau Compact Object Header in Java 25\" 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 class=\"wp-block-paragraph\">Der Compact Object Header ist nicht mehr in Mark Word und Class Word unterteilt. Er besteht nun aus:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>22 Bit<\/strong> f\u00fcr den Class Pointer (statt bisher 32),<\/li>\n\n\n\n<li><strong>31 Bit<\/strong> f\u00fcr den Identity Hash Code (unver\u00e4ndert),<\/li>\n\n\n\n<li><strong>4 reservierte Bits<\/strong> f\u00fcr Project Valhalla,<\/li>\n\n\n\n<li><strong>4 Bit<\/strong> f\u00fcr das Objektalter (unver\u00e4ndert),<\/li>\n\n\n\n<li><strong>2 Bit<\/strong> f\u00fcr Locking-Informationen (Tag Bits, unver\u00e4ndert),<\/li>\n\n\n\n<li><strong>1 Bit<\/strong> f\u00fcr das neue <em>Self Forwarded Tag<\/em>.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Was wurde ge\u00e4ndert?<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Unbenutzte Bits entfernt:<\/strong> Im bisherigen Aufbau gab es 27 ungenutzte Bits im Mark Word (25 am Anfang und je eines vor und nach den Age Bits) \u2013 diese wurden entfernt.<\/li>\n\n\n\n<li><strong>Class Pointer komprimiert:<\/strong> Der 32-Bit-Zeiger auf die Klassendatenstruktur wurde auf 22 Bit reduziert \u2013 wie das genau funktioniert, erf\u00e4hrst du im <a href=\"https:\/\/www.happycoders.eu\/de\/java\/compact-object-headers\/\">Hauptartikel \u00fcber Compact Object Headers<\/a>.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-24-features\/#compact-object-headers-experimental-jep-450\">Java 24<\/a> wurden Compact Object Headers als experimentelles Feature vorgestellt. Da sie sich als stabil und performant erwiesen haben, werden sie in Java 25 durch <a href=\"https:\/\/openjdk.org\/jeps\/519\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 519<\/a> zum produktiven Feature erkl\u00e4rt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Aktivieren kannst du sie mit folgender VM-Option:<\/p>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\"><code>-XX:+UseCompactObjectHeaders<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die zus\u00e4tzliche Freischaltung experimenteller Features durch <code>-XX:+UnlockExperimentalVMOptions<\/code> ist in Java 25 nicht mehr erforderlich.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Mehr Details findest du im oben bereits erw\u00e4hnten <a href=\"https:\/\/www.happycoders.eu\/de\/java\/compact-object-headers\/\">Hauptartikel \u00fcber Compact Object Headers<\/a>.<\/p>\n\n\n\n<div class=\"wp-block-uagb-container uagb-block-0c32d8ba alignfull uagb-is-root-container\">\n<div class=\"uagb-block-562b19ac uagb-infobox__content-wrap  uagb-infobox-icon-left uagb-infobox-left uagb-infobox-stacked-mobile uagb-infobox-image-valign-top \"><div class=\"uagb-ifb-icon-wrap\"><svg xmlns=\"https:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\"><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><\/div><div class=\"uagb-ifb-content\"><div class=\"uagb-ifb-title-wrap\"><\/div><p class=\"uagb-ifb-desc\"><strong>Ausblick:<\/strong> <br><br>In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-27-features\/#compact-object-headers-by-default-jep-534\">Java 27<\/a> werden Compact Object Headers per <a href=\"https:\/\/openjdk.org\/jeps\/534\" target=\"_blank\" rel=\"noopener\">JEP 534<\/a> zum Standard \u2013 du musst sie dann nicht mehr explizit aktivieren, sondern kannst sie bei Bedarf mit <code>-XX:-UseCompactObjectHeaders<\/code> abschalten.<\/p><\/div><\/div>\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"generational-shenandoah-jep-521\">Generational Shenandoah \u2013 JEP 521<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-24-features\/#generational-shenandoah-experimental-jep-404\">Java 24<\/a> wurde der <em>Generational Mode<\/em> f\u00fcr den Shenandoah-Garbage-Collector als experimentelles Feature eingef\u00fchrt. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ein Generational Garbage Collector macht sich die sogenannte \u201eSchwache Generationshypothese\u201c zunutze: Die meisten Objekte sterben kurz nach ihrer Erstellung, w\u00e4hrend langlebige Objekte typischerweise noch l\u00e4nger bestehen bleiben.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Um diese Eigenschaft effizient zu nutzen, unterteilt der Garbage Collector den Heap in zwei Bereiche \u2013 eine junge und eine alte Generation. Neue Objekte landen zun\u00e4chst im Young Space. Nur wenn sie mehrere GC-Zyklen \u00fcberleben, werden sie in den Old Space verschoben. Aufgrund der erwarteten Stabilit\u00e4t der alten Generation wird diese seltener gescannt \u2013 das reduziert die Anzahl unn\u00f6tiger Scans und verk\u00fcrzt im Idealfall die Pausenzeiten deutlich.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Diese Strategie ist nicht neu: Der G1 Garbage Collector \u2013 seit Java 7 im Einsatz \u2013 arbeitet schon immer generationenbasiert. Auch der ZGC verwendet 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 einen vergleichbaren Ansatz. Mit Java 24 zog Shenandoah nach, zun\u00e4chst nur im experimentellen Modus. Die Implementierung erwies sich in der Praxis als stabil und leistungsf\u00e4hig: Nutzer:innen berichteten von positiven Ergebnissen bei latenzsensitiven Anwendungen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In Java 25 wird der Generational Mode nun durch <a href=\"https:\/\/openjdk.org\/jeps\/521\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 521<\/a> zu einem produktiven Feature erkl\u00e4rt. Du kannst ihn ab sofort wie folgt aktivieren:<\/p>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\"><code>-XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die zus\u00e4tzliche Option <code>-XX:+UnlockExperimentalVMOptions<\/code> ist nicht mehr erforderlich.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"ahead-of-time-command-line-ergonomics-jep-514\">Ahead-of-Time Command-Line Ergonomics \u2013 JEP 514<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Beim Start einer Java-Anwendung kann es mitunter Sekunden bis Minuten dauern, bis alle Java-Klassen gelesen, geparst, geladen und gelinkt sind. Durch das in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-24-features\/#ahead-of-time-class-loading-linking-jep-483\">Java 24<\/a> eingef\u00fchrte, auf Application Class Data Sharing (AppCDS) basierende, <a href=\"https:\/\/www.happycoders.eu\/de\/java\/ahead-of-time-class-loading-and-linking\/\">Ahead-of-Time Class Loading and Linking<\/a> k\u00f6nnen diese Schritte <em>vor<\/em> dem Start der Anwendung ausgef\u00fchrt werden und dadurch der Start der Anwendung signifikant beschleunigt werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Der Vorgang bestand bisher aus drei Schritten:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Schritt 1: <\/strong>Im \u201eRecord Mode\u201c analysiert die JVM die Anwendung in einem Trainingslauf und speichert Informationen \u00fcber die geladenen und gelinkten Klassen in der AOT-Konfiguration (im Beispiel <code>AotTest.conf<\/code>):<\/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\">java -XX:AOTMode=record -XX:AOTConfiguration=AotTest.conf \\\n    -cp AotTest.jar eu.happycoders.AotTest<\/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 class=\"wp-block-paragraph\"><strong>Schritt 2: <\/strong>Im \u201eCreate Mode\u201c erzeugt die JVM aus der AOT-Konfiguration den AOT-Cache (<code>AotTest.aot<\/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\">java -XX:AOTMode=create -XX:AOTConfiguration=AotTest.conf -XX:AOTCache=AotTest.aot \\\n    -cp AotTest.jar<\/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 class=\"wp-block-paragraph\"><strong>Schritt 3: <\/strong>Bei jedem weiteren Start der Anwendung l\u00e4dt die JVM die Klassen in geladener und gelinkter Form direkt aus diesem Cache und startet dementsprechend schneller:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"MIPS Assembly\" data-shcb-language-slug=\"mipsasm\"><span><code class=\"hljs language-mipsasm\"><span class=\"hljs-keyword\">java <\/span>-XX:AOTCache=AotTest.aot -cp AotTest.<span class=\"hljs-keyword\">jar <\/span>eu.happycoders.AotTest<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">MIPS Assembly<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">mipsasm<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">(Im oben verlinkten Artikel wirst du Schritt f\u00fcr Schritt durch diesen Prozess gef\u00fchrt.)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/openjdk.org\/jeps\/514\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 514<\/a> f\u00fchrt die neue Kommandozeilen-Option <code>-XX:AOTCacheOutput<\/code> ein, mit der die ersten beiden Schritte durch ein einziges Kommando ausgef\u00fchrt werden k\u00f6nnen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">java -XX:AOTCacheOutput=AotTest.aot -cp AotTest.jar eu.happycoders.AotTest<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><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 class=\"wp-block-paragraph\">\u00dcber die neue Umgebungsvariable <code>JDK_AOT_VM_OPTIONS<\/code> k\u00f6nnen VM-Optionen angegeben werden, die nur f\u00fcr den zweiten Teilschritt (\u201eCreate Mode\u201c) gelten sollen \u2013 ohne den ersten Teilschritt, den Trainingslauf (\u201eRecord Mode\u201c), zu beeinflussen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Der neue kombinierte Modus ersetzt die zwei alten Modi nicht, da es Use Cases gibt, in denen es sinnvoll sein kann, die Schritte nach wie vor separat auszuf\u00fchren. Zum Beispiel, wenn Schritt 1 (der Trainingslauf) auf einer kleinen Cloud-Instanz ausgef\u00fchrt werden soll \u2013 Schritt 2 (die Cache-Erzeugung, die durch neue Optimierungen in Zukunft deutlich l\u00e4nger dauern kann) hingegen auf einer leistungsf\u00e4higeren Maschine.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"ahead-of-time-method-profiling-jep-515\">Ahead-of-Time Method Profiling \u2013 JEP 515<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Wenn eine Java-Anwendung l\u00e4uft, sammelt die JVM kontinuierlich Daten \u00fcber die aufgerufenen Methoden, insbesondere dar\u00fcber, welche Methoden die meiste CPU-Zeit ben\u00f6tigen. Diese Methoden werden dann dynamisch optimiert und in Assembler-Code f\u00fcr die Zielplattform \u00fcbersetzt. Da dieser Vorgang eine Weile dauert, ist eine Java-Anwendung zu Beginn \u2013 in der sogenannten Aufw\u00e4rmphase (\u201ewarm-up phase\u201c) \u2013 langsamer und erreicht ihre volle Leistungsf\u00e4higkeit erst nach einigen Sekunden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Durch <a href=\"https:\/\/www.happycoders.eu\/de\/java\/ahead-of-time-class-loading-and-linking\/\">Ahead-of-Time Class Loading and Linking<\/a> wird \u2013 wie im vorherigen Abschnitt beschrieben \u2013 durch einen Trainingslauf ein AOT-Cache erzeugt, der die von einer Anwendung ben\u00f6tigten Klassen in geladener und gelinkter Form enth\u00e4lt und so den Start einer Anwendung beschleunigt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/openjdk.org\/jeps\/515\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 515<\/a> erweitert Trainingslauf und AOT-Cache dahingehend, dass zus\u00e4tzlich zu den bin\u00e4ren Klassendaten auch die o. g. Daten \u00fcber die CPU-Nutzung von Methoden (die sogenannten \u201eMethoden-Profile\u201c) im AOT-Cache gespeichert werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Somit k\u00f6nnen beim Programmstart direkt die am h\u00e4ufigsten aufgerufenen Methoden (die sogenannten \u201eHotspots\u201c) in Maschinencode \u00fcbersetzt werden. Dadurch wurden Verbesserungen der Startzeit um bis zu 19 % gemessen, w\u00e4hrend die Gr\u00f6\u00dfe des AOT-Caches lediglich um 2,5 % zugenommen hat.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die \u00c4nderungen durch JEP 515 haben keinen Einfluss auf die kontinuierliche Analyse von Methodenaufrufen und die weitere Optimierung zur Laufzeit, sodass die Anwendung auch bei \u00c4nderungen ihres Verhaltens im Produktionsbetrieb weiterhin kontinuierlich durch die JVM optimiert wird.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"verbesserungen-am-java-flight-recorder-jfr\">Verbesserungen am Java Flight Recorder (JFR)<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Der Java Flight Recorder (JFR) ist ein seit <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-11-features\/#java-flight-recorder\">Java 11<\/a> in die JVM eingebautes Tool zur Diagnose von Java-Anwendungen. Mit dem JFR lassen sich die Anwendung profilen und bestimmte Ereignisse erfassen, ohne dabei die Leistung der Anwendung wesentlich zu beeintr\u00e4chtigen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Java 25 enth\u00e4lt drei Verbesserungen am Java Flight Recorder \u2013 davon eine noch im <em>Experimental<\/em>-Status.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"jfr-cooperative-sampling-jep-518\">JFR Cooperative Sampling \u2013 JEP 518<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Eine Funktion des Java Flight Recorders ist das \u201eProfiling\u201c. Dabei geht es nicht um einzelne Events, sondern um Statistiken z. B. dar\u00fcber, welche Methoden wie viel Zeit in Anspruch nehmen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Das erfolgt nicht durch exakte Messung, sondern durch sogenanntes \u201eSampling\u201c: Dabei werden in festen Intervallen die Aufrufstacks aller Threads ausgelesen und gespeichert. Aus den gespeicherten Call Stacks wird dann durch statistische Methoden die ungef\u00e4hre Aufrufdauer aller Methoden abgeleitet.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Das Auslesen eines genauen Stack Traces ist allerdings nur an sogenannten \u201eSafepoints\u201c m\u00f6glich \u2013 das sind festgelegte Stellen im Code der JVM, an denen bestimmte, daf\u00fcr erforderliche Metadaten verf\u00fcgbar sind. Das Auslesen ausschlie\u00dflich an diesen Safepoints f\u00fchrt allerdings zum sogenannten \u201eSafepoint Bias\u201c: Wenn oft aufgerufener Code \u00fcberdurchschnittlich h\u00e4ufig fernab eines Safepoints ausgef\u00fchrt wird, wird er ungenau gemessen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Aus diesem Grund wurde das Sampling bisher eben <em>nicht<\/em> nur an diesen \u201eSafepoints\u201c durchgef\u00fchrt. Ohne die an den Safepoints verf\u00fcgbaren Metadaten mussten allerdings Heuristiken eingesetzt werden, um den Aufrufstack zu generieren. Diese Heuristiken sind jedoch \u00e4u\u00dferst ineffizient und k\u00f6nnen im Worst Case die JVM zum Absturz bringen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Daher wurde durch <a href=\"https:\/\/openjdk.org\/jeps\/518\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 518<\/a> der Sampling-Mechanismus wie folgt modifiziert:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>An den regelm\u00e4\u00dfigen Sampling-Intervallen wird nur noch der <em>Program Counter<\/em> und der <em>Stack Pointer<\/em> der CPU ausgelesen.<\/li>\n\n\n\n<li>Stack Traces werden an den darauf folgenden Safepoints ausgelesen.<\/li>\n\n\n\n<li>Anhand des aufgezeichneten <em>Program Counters<\/em> und <em>Stack Pointers<\/em> wird der Aufrufstack zum Sampling-Zeitpunkt rekonstruiert.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Dieser Ansatz ist zum einen performanter, zum anderen unkomplizierter in der Implementierung und dadurch stabiler.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"jfr-method-timing-tracing-jep-520\">JFR Method Timing &amp; Tracing \u2013 JEP 520<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Im vorherigen Abschnitt habe ich beschrieben, wie das Profiling des Java Flight Recorders (JFR) funktioniert: Zu bestimmten Zeitpunkten werden Aufrufstacks aller Threads ausgelesen und daraus durch statistische Berechnungen die ungef\u00e4hren Aufrufh\u00e4ufigkeiten und -dauern aller Methoden abgeleitet. Dieses Verfahren ist allerdings ungenau und wird nie die <em>exakte<\/em> Aufrufzahl und -dauer ermitteln k\u00f6nnen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Drittanbieter wie <a href=\"https:\/\/www.ej-technologies.com\/jprofiler\" target=\"_blank\" rel=\"noopener\">JProfiler<\/a>, <a href=\"https:\/\/www.yourkit.com\/\" target=\"_blank\" rel=\"noopener\">YourKit<\/a> oder <a href=\"https:\/\/www.datadoghq.com\/\" target=\"_blank\" rel=\"noopener\">DataDog<\/a> stellen seit jeher Tools zur Verf\u00fcgung, die sich als sogenannter <em>Java Agent<\/em> mit der JVM verbinden und in die zu messenden Methoden Code einschleusen, der die Aufrufh\u00e4ufigkeit und -dauer exakt misst. Das hat nat\u00fcrlich einen gewissen Overhead zur Folge.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Durch <a href=\"https:\/\/openjdk.org\/jeps\/520\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 520<\/a> wird nun innerhalb der JVM die M\u00f6glichkeit geschaffen, Methodenaufrufe und deren Dauer exakt zu messen. Dabei k\u00f6nnen \u00fcber Filter bestimmte Klassen, bestimmte Methoden oder Methoden mit bestimmten Annotationen ausgew\u00e4hlt werden. Die Vorteile: h\u00f6here Genauigkeit gegen\u00fcber Sampling und weniger Overhead gegen\u00fcber dem Einsatz von Drittanbieter-Agents.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Mit folgenden Optionen kannst du beispielsweise den StackTrace aller Interaktionen mit HashMaps protokollieren:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-22\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">java -XX:StartFlightRecording:jdk.MethodTrace#filter=java.util.HashMap,filename=recording.jfr Demo.java<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><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 class=\"wp-block-paragraph\">So gibst du dann die StackTraces aus:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-23\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">jfr print --events jdk.MethodTrace --stack-depth 20 recording.jfr<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><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 class=\"wp-block-paragraph\">Die Aufrufzeiten hingegen kannst du wie folgt protokollieren und ausgeben:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-24\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">java -XX:StartFlightRecording:jdk.MethodTiming#filter=java.util.HashMap,filename=recording.jfr Demo.java\njfr print --events jdk.MethodTiming recording.jfr<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-24\"><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<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"jfr-cpu-time-profiling-experimental-jep-509\">JFR CPU-Time Profiling (Experimental) \u2013 JEP 509<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Im Abschnitt <a href=\"#jfr-cooperative-sampling-jep-518\">JFR Cooperative Sampling<\/a> habe ich beschrieben, wie durch das Auslesen von Stack Traces in festen Intervallen die Aufrufh\u00e4ufigkeit und -dauer von Methoden abgeleitet werden kann.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bei den dabei ermittelten Zeiten handelt es sich um die sogenannte <em>Ausf\u00fchrungszeit<\/em>, also diejenige Zeit, die vom Eintritt in die Methode bis zum Austritt vergangen ist. Diese Zeit ist unabh\u00e4ngig davon, wie die Methode die CPU eingesetzt hat. Eine Methode, die eine Sekunde lang einen Sortieralgorithmus ausf\u00fchrt, und dabei zu 100 % die CPU auslastet, hat die gleiche Ausf\u00fchrungszeit wie eine Methode, die eine Anfrage an die Datenbank schickt und eine Sekunde lang auf die Antwort wartet \u2013 was hingegen nur minimale CPU-Ressourcen in Anspruch nimmt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Diejenige Zeit, w\u00e4hrend der die Methode die CPU nutzt, wird <em>CPU-Zeit<\/em> genannt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wenn wir wissen, welche Methoden die meiste CPU-Zeit nutzen, k\u00f6nnen wir diese Methoden optimieren, z. B. indem wir einen Suchalgorithmus gegen einen effizienteren austauschen \u2013 und dadurch die CPU-Last der Anwendung reduzieren.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bisher bot der Java Flight Recorder keine M\u00f6glichkeit, die CPU-Zeit zu analysieren. Das \u00e4ndert sich durch <a href=\"https:\/\/openjdk.org\/jeps\/509\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 509<\/a> \u2013 zun\u00e4chst allerdings nur f\u00fcr Linux.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Durch die neue Option <code>jdk.CPUTimeSample#enabled=true<\/code> l\u00e4sst sich das CPU-Zeit-Sampling aktivieren. Mit dem folgenden Kommando beispielsweise startest du eine Java-Anwendung mit aktiviertem CPU-Zeit-Sampling und mit der Ausgabe der gemessenen Daten in die Datei <em>profile.jfr<\/em>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-25\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">java -XX:StartFlightRecording=jdk.CPUTimeSample#enabled=true,filename=profile.jfr ...<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-25\"><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 class=\"wp-block-paragraph\">Die neue Option ist unabh\u00e4ngig von der Option <code>jdk.ExecutionSample#enabled=true<\/code>, mit der das <em>Ausf\u00fchrungszeit<\/em>-Sampling aktiviert wird \u2013 du kannst also auch beide Sampling-Methoden gleichzeitig aktivieren und damit Ausf\u00fchrungszeiten <em>und<\/em> CPU-Zeiten messen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>CPU-Time Profiling<\/em> ist aktuell nur f\u00fcr Linux verf\u00fcgbar und noch im <em>Experimental<\/em>-Stadium. Da es sich dabei nicht um eine regul\u00e4re VM-Option handelt, sondern um eine JFR-Option, brauchst du zur Aktivierung <em>nicht<\/em> die VM-Option <code style=\"white-space:nowrap\">-XX:+UnlockExperimentalVMOptions<\/code> angeben.<\/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=\"neue-preview-features-in-java-25\">Neue Preview-Features in Java 25<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Auch wenn Java 25 ein Long-Term-Support-Release ist, ist das kein Grund f\u00fcr die JDK-Entwickler:innen, keine neuen Preview-Features zu ver\u00f6ffentlichen. Ein besonders interessantes Preview-Feature sind Stable Values \u2013 Werte, die beim ersten Zugriff darauf einmalig initialisiert werden und danach konstant sind, so dass der Zugriff darauf durch die JVM optimiert werden kann.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Preview-Features sind nicht f\u00fcr den produktiven Einsatz gedacht, sondern zum ersten Experimentieren und m\u00fcssen mit folgenden VM-Optionen aktiviert werden:<\/p>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\"><code>--enable-preview --source 25<\/code><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"stable-values-preview-jep-502\">Stable Values (Preview) \u2013 JEP 502<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Stable Values<\/em> l\u00f6sen ein altes Problem \u2013 die saubere, performante und threadsichere Initialisierung von Werten, die nicht beim Programmstart gesetzt werden sollen (oder k\u00f6nnen), sondern erst beim ersten Zugriff darauf.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Warum brauchen wir Stable Values?<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Unver\u00e4nderliche Werte (Immutability) machen Code einfacher, sicherer und erm\u00f6glichen der JVM weitreichende Performance-Optimierungen wie z. B. <a href=\"https:\/\/de.wikipedia.org\/wiki\/Compiler#Statische_Formelauswertung_zur_%C3%9Cbersetzungszeit\" target=\"_blank\" rel=\"noopener\">Constant Folding<\/a>. Bisher war dies nur durch die Markierung eines Feldes als <code>final<\/code> m\u00f6glich. Finale Felder werden allerdings sofort beim Laden einer Klasse (finale statische Felder) oder beim Erzeugen eines Objekts (finale Instanzfelder) initialisiert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wenn die Initialisierung aber aufw\u00e4ndig oder kontextabh\u00e4ngig ist \u2013 etwa weil ein Dienst erst sp\u00e4ter verf\u00fcgbar ist \u2013, m\u00fcssen wir uns mit verschiedenen Varianten der Lazy-Initialisierungen begn\u00fcgen. Triviale Implementierungen sind oft nicht threadsicher, und threadsichere Varianten, wie z. B. das <a href=\"https:\/\/www.happycoders.eu\/de\/java\/double-checked-locking\/\">Double-Checked Locking Idiom<\/a> sind schwer korrekt zu implementieren und damit fehleranf\u00e4llig. Im Endeffekt sind alle verf\u00fcgbaren L\u00f6sungen Workarounds und schlie\u00dfen JVM-Optimierungen aus.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Hier ein Beispiel f\u00fcr eine triviale, nicht threadsichere Implementierung, um Programm-Einstellungen beim ersten Zugriff darauf aus einer Datenbank zu laden:<\/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-keyword\">private<\/span> Settings settings;\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">private<\/span> Settings <span class=\"hljs-title\">getSettings<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (settings == <span class=\"hljs-keyword\">null<\/span>) {\n        settings = loadSettingsFromDatabase();\n    }\n    <span class=\"hljs-keyword\">return<\/span> settings;\n}\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> Locale <span class=\"hljs-title\">getLocale<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n    <span class=\"hljs-keyword\">return<\/span> getSettings().getLocale();\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 class=\"wp-block-paragraph\">Mit <code>synchronized<\/code> k\u00f6nnten wir die <code>getSettings()<\/code>-Methode threadsicher machen, das w\u00e4re allerdings nicht sehr performant. Eine threadsichere und performante \u2013 gleichzeitig aber deutlich komplexere \u2013 Variante findest du im Abschnitt <a href=\"https:\/\/www.happycoders.eu\/de\/java\/double-checked-locking\/#optimiertes-double-checked-locking-in-java\">Optimiertes Double-Checked Locking in Java<\/a> im Artikel \u00fcber das Double-Checked Locking.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Die L\u00f6sung: Stable Values<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Stable Values<\/em> schlie\u00dfen die L\u00fccke zwischen <code>final<\/code> und ver\u00e4nderlich:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Sie lassen sich genau einmal initialisieren \u2013 zu beliebigem Zeitpunkt und threadsicher.<\/li>\n\n\n\n<li>Danach gelten sie als unver\u00e4nderlich, sodass die JVM sie wie <code>final<\/code>-Felder optimieren kann.<\/li>\n\n\n\n<li>Sie eliminieren typische Fehlerquellen in selbstgebauten Lazy-Initialisierungen.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Hier das Beispiel von oben mit einem Stable Value:<\/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-keyword\">private<\/span> <span class=\"hljs-keyword\">final<\/span> Supplier&lt;Settings&gt; settings =\n        StableValue.supplier(<span class=\"hljs-keyword\">this<\/span>::loadSettingsFromDatabase);\n\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> Locale <span class=\"hljs-title\">getLocale<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n    <span class=\"hljs-keyword\">return<\/span> settings.get().getLocale(); <span class=\"hljs-comment\">\/\/ \u27f5 Here we access the stable value<\/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 class=\"wp-block-paragraph\">Beim ersten Aufruf von <code>settings.get(\u2026)<\/code> wird <code>loadSettingsFromDatabase()<\/code> aufgerufen und die Einstellungen innerhalb von <code>settings<\/code> gespeichert. Alle weiteren Zugriffe liefern dann den gespeicherten Wert. Das ganze l\u00e4uft threadsicher ab, d. h. wenn <code>get(\u2026)<\/code> gleichzeitig aus mehreren Threads heraus aufgerufen wird, wird nur in einem der Threads <code>loadSettingsFromDatabase()<\/code> aufgerufen. Die anderen Threads warten, bis der Wert zur Verf\u00fcgung steht.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Auch als Liste nutzbar<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Mit <code>StableValue.list()<\/code> l\u00e4sst sich eine Liste definieren, deren Elemente bei Zugriff initialisiert und danach eingefroren werden. Beispiel:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-28\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">List&lt;Double&gt; squareRoots = StableValue.list(<span class=\"hljs-number\">100<\/span>, Math::sqrt);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-28\"><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 class=\"wp-block-paragraph\">Erst beim ersten Zugriff auf ein Listenelement \u2013 sei es mit <code>first()<\/code>, <code>get(int index)<\/code>, <code>last()<\/code> oder bei einer Iteration \u2013 wird dieses berechnet. Danach bleibt es konstant, und weitere Zugriffe darauf k\u00f6nnen von der JVM \u2013 genau wie Zugriffe auf Konstanten \u2013 optimiert werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Neben <em>Stable Lists<\/em> gibt es auch <em>Stable Maps<\/em>, <em>Stable Functions<\/em> und <em>Stable IntFunctions<\/em>.<\/p>\n\n\n\n<div class=\"wp-block-uagb-container uagb-block-0d01c50e alignfull uagb-is-root-container\">\n<div class=\"uagb-block-568519d4 uagb-infobox__content-wrap  uagb-infobox-icon-left uagb-infobox-left uagb-infobox-stacked-mobile uagb-infobox-image-valign-top \"><div class=\"uagb-ifb-icon-wrap\"><svg xmlns=\"https:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\"><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><\/div><div class=\"uagb-ifb-content\"><div class=\"uagb-ifb-title-wrap\"><\/div><p class=\"uagb-ifb-desc\"><strong>Hinweis f\u00fcr Java 26 und neuer:<\/strong><br><br>Seit <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-26-features\/#lazy-constants-second-preview-jep-526\">Java 26<\/a> hei\u00dft dieses Feature <strong>Lazy Constants<\/strong> \u2013 und die API wurde dabei deutlich umgebaut: Aus <code>StableValue<\/code> wird <code>LazyConstant<\/code>, die Factory-Methoden f\u00fcr Listen und Maps sind nach <code>List.ofLazy(\u2026)<\/code> bzw. <code>Map.ofLazy(\u2026)<\/code> gewandert, und die Low-Level-Methoden sowie die <code>Function<\/code>-\/<code>IntFunction<\/code>-Varianten sind entfallen. Die Beispiele in diesem Abschnitt zeigen die urspr\u00fcngliche Java-25-Preview-API. Die aktuelle Variante findest du im Hauptartikel.<\/p><\/div><\/div>\n<\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Die vollst\u00e4ndige Stable Value API sowie eine ausf\u00fchrliche Erkl\u00e4rung zur internen Funktionsweise findest du im <a href=\"https:\/\/www.happycoders.eu\/de\/java\/lazy-constants\/\">Hauptartikel \u00fcber Stable Values<\/a>. Dort gehe ich auch n\u00e4her auf die bisherigen Workarounds und deren Nachteile ein.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Stable Values werden durch <a href=\"https:\/\/openjdk.org\/jeps\/502\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 502<\/a> in Java 25 als Preview-Feature ver\u00f6ffentlicht.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"pem-encodings-of-cryptographic-objects-preview-jep-470\">PEM Encodings of Cryptographic Objects (Preview) \u2013 JEP 470<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">PEM (Privacy-Enhanced Mail) ist ein weit verbreitetes Format zur Speicherung von kryptografischen Schl\u00fcsseln und Zertifikaten. Ein Zertifikat im PEM-Format sieht z. B. so aus:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-29\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">-----BEGIN CERTIFICATE-----\nMIIDtzCCAz2gAwIBAgISBUCeYELtjMmr4FAIqHapebbFMAoGCCqGSM49BAMDMDIx\nCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQDEwJF\n. . .\nDBeMde1YpWNXpF9+B\/OMKgn7RgXRj5b2QpBCnFsP92T4cK\/Nn+xFIjYCMCCx4E79\ntoSQBlYnNHv0eXnWkI8TmXsU\/A6rU4Gxdr9GbGixgRJvkw0C6zjL\/lH2Vg==\n-----END CERTIFICATE-----<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-29\"><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 class=\"wp-block-paragraph\">Wer schon einmal versucht hat, Schl\u00fcssel oder Zertifikate im PEM-Format in eine Java-Anwendung zu importieren oder aus dieser zu exportieren, wird nach m\u00fchevoller Stack-Overflow-Recherche festgestellt haben: Java bietet hierf\u00fcr keine direkte M\u00f6glichkeit.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr das Dekodieren eines verschl\u00fcsselten Private Keys im PEM-Format beispielsweise sind \u00fcber ein Dutzend Code-Zeilen n\u00f6tig:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-30\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">String encryptedPrivateKeyPemEncoded = . . .\nString passphrase = . . .\n\nString encryptedPrivateKeyBase64Encoded = encryptedPrivateKeyPemEncoded\n        .replace(<span class=\"hljs-string\">\"-----BEGIN ENCRYPTED PRIVATE KEY-----\"<\/span>, <span class=\"hljs-string\">\"\"<\/span>)\n        .replace(<span class=\"hljs-string\">\"-----END ENCRYPTED PRIVATE KEY-----\"<\/span>, <span class=\"hljs-string\">\"\"<\/span>)\n        .replaceAll(<span class=\"hljs-string\">\"&#091;\\\\r\\\\n]\"<\/span>, <span class=\"hljs-string\">\"\"<\/span>);\n\nBase64.Decoder decoder = Base64.getDecoder();\n<span class=\"hljs-keyword\">byte<\/span>&#091;] encryptedPrivateKeyBytes = decoder.decode(encryptedPrivateKeyBase64Encoded);\nEncryptedPrivateKeyInfo encryptedPrivateKeyInfo =\n        <span class=\"hljs-keyword\">new<\/span> EncryptedPrivateKeyInfo(encryptedPrivateKeyBytes);\n\nString algorithmName = encryptedPrivateKeyInfo.getAlgName();\nSecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance(algorithmName);\n\nPBEKeySpec pbeKeySpec = <span class=\"hljs-keyword\">new<\/span> PBEKeySpec(passphrase.toCharArray());\nKey pbeKey = secretKeyFactory.generateSecret(pbeKeySpec);\n\nCipher cipher = Cipher.getInstance(algorithmName);\nAlgorithmParameters algParams = encryptedPrivateKeyInfo.getAlgParameters();\ncipher.init(Cipher.DECRYPT_MODE, pbeKey, algParams);\n\nKeyFactory rsaKeyFactory = KeyFactory.getInstance(<span class=\"hljs-string\">\"RSA\"<\/span>);\nKeySpec keySpec = encryptedPrivateKeyInfo.getKeySpec(cipher);\nPrivateKey privateKey = rsaKeyFactory.generatePrivate(keySpec);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-30\"><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 class=\"wp-block-paragraph\">Das in Java 25 als Preview vorgestellte Feature <em>PEM Encodings of Cryptographic Objects<\/em> soll das signifikant vereinfachen. Das Code-Monstrum oben l\u00e4sst sich in Java 25 mit aktivierten Preview-Features wie folgt vereinfachen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-31\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">PrivateKey privateKey = PEMDecoder.of()\n        .withDecryption(passphrase.toCharArray())\n        .decode(encryptedPrivateKeyPemEncoded, PrivateKey<span class=\"hljs-class\">.<span class=\"hljs-keyword\">class<\/span>)<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-31\"><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 class=\"wp-block-paragraph\">Aus 18 Zeilen Code sind drei Zeilen geworden!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Genauso einfach l\u00e4sst sich ein Private Key verschl\u00fcsseln und ins PEM-Format umwandeln:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-32\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">String encryptedPrivateKeyPemEncoded = PEMEncoder.of()\n        .withEncryption(passphrase.toCharArray())\n        .encodeToString(privateKey);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-32\"><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 class=\"wp-block-paragraph\">Im Zentrum des neuen Features stehen die Klassen <code>PEMEncoder<\/code> und <code>PEMDecoder<\/code> sowie das Interface <code>DEREncodable<\/code>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Alle Klassen, die kryptografische Schl\u00fcssel und Zertifikate repr\u00e4sentieren (wie <code>PrivateKey<\/code> im Beispiel oben), implementieren das neue Interface <code>DEREncodable<\/code>.<\/li>\n\n\n\n<li>Ein <code>PEMEncoder<\/code> wird \u2013 wie oben gezeigt \u2013 mit der statischen Methode <code>PEMEncoder.of()<\/code> erzeugt. Mit den Instanzmethoden <code>encode(...)<\/code> und <code>encodeToString(...)<\/code> lassen sich dann kryptografische Objekte ins PEM-Format umwandeln (bin\u00e4r oder als String).<\/li>\n\n\n\n<li>Ein <code>PEMDecoder<\/code> wird mit der statischen Methode <code>PEMDecoder.of()<\/code> erzeugt. PEM-Dateien lassen sich dann mit der <code>decode()<\/code>-Methode in ein kryptografisches Objekt umwandeln. <\/li>\n\n\n\n<li>Die <code>PEMDecoder.decode()<\/code>-Methode gibt es auch ohne den zweiten Parameter, der im Beispiel oben den erwarteten R\u00fcckgabetyp <code>PrivateKey.class<\/code> angibt. Diese Variante gibt ein <code>DEREncodable<\/code> zur\u00fcck, welches dann z. B. mit <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-21-features\/#pattern-matching-for-switch-jep-441\">Pattern Matching for switch<\/a> ausgewertet werden kann.<\/li>\n\n\n\n<li>Um einen Private Key zu verschl\u00fcsseln, muss der <code>PEMEncoder<\/code> \u2013 wie im Beispiel oben \u2013 mit <code>PEMEncoder.of().withEncryption(passphrase)<\/code> erzeugt werden. Um ihn wieder zu entschl\u00fcsseln muss der <code>PEMDecoder<\/code> analog dazu mit <code>PEMDecoder.of().withDecryption(passphrase)<\/code> erzeugt werden.<\/li>\n\n\n\n<li><code>PEMEncoder<\/code>- und <code>PEMDecoder<\/code>-Instanzen sind statuslos und threadsicher \u2013 somit kann eine einzige Instanz von mehreren Threads gemeinsam genutzt und wiederverwendet werden.<\/li>\n\n\n\n<li>Sollte die <code>decode()<\/code>-Methode die PEM-Daten nicht dekodieren k\u00f6nnen, wird keine Exception geworfen, sondern ein generisches <code>PEMRecord<\/code>-Objekt zur\u00fcckgeliefert, das die Bin\u00e4rdaten der PEM-Datei enth\u00e4lt.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">PEM Encodings of Cryptographic Objects ist in <a href=\"https:\/\/openjdk.org\/jeps\/470\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 470<\/a> spezifiziert.<\/p>\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 class=\"wp-block-paragraph\">Drei Features haben es nicht geschafft, in Java 25 finalisiert zu werden und gehen in eine neue Preview- bzw. Incubator-Runde: <em>Structured Concurrency<\/em>, <em>Primitive Type Patterns<\/em> und \u2013 wenig \u00fcberraschend \u2013 die <em>Vector API<\/em>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"structured-concurrency-fifth-preview-jep-505\">Structured Concurrency (Fifth Preview) \u2013 JEP 505<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Wenn eine Aufgabe in mehrere Teilaufgaben zerlegt werden kann, die unabh\u00e4ngig voneinander und parallel ausgef\u00fchrt werden, kannst du mit Structured Concurrency diese Teilaufgaben klar gegliedert, nachvollziehbar und effizient koordinieren.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Statt komplexer und fehleranf\u00e4lliger Logik mit z. B. <code>ExecutorService<\/code> oder parallelen Streams erhalten wir eine API, die Start, Abschluss und Fehlerbehandlung aller Subtasks in einem klar abgegrenzten Codeblock zusammenfasst.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Structured-Concurrency-Scopes lassen sich beliebig verschachteln. So kannst du komplexe Aufgabenstrukturen klar modellieren und beh\u00e4ltst dabei jederzeit den \u00dcberblick und die Kontrolle \u00fcber den Lebenszyklus s\u00e4mtlicher Subtasks:<\/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=\"nested structured concurrency\" 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 class=\"wp-block-paragraph\">Mit Java 25 geht Structured Concurrency bereits in die f\u00fcnfte Preview-Runde \u2013 erstmals seit der ersten Preview-Version in Java 21 jedoch mit wesentlichen \u00c4nderungen an der API. Die Neuerungen werden in <a href=\"https:\/\/openjdk.org\/jeps\/505\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 505<\/a> spezifiziert und basieren auf umfangreichem Feedback aus der Community.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Falls du dich noch nicht mit Structured Concurrency besch\u00e4ftigt hast und daher nicht an den \u00c4nderungen interessiert bist, spring gerne direkt zum Abschnitt <a href=\"#Beispiel_Die_schnellste_Antwort_gewinnt\">Beispiel: Die schnellste Antwort gewinnt<\/a>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Was ist neu in Java 25?<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Die Art und Weise, wie ein <code>StructuredTaskScope<\/code> ge\u00f6ffnet wird, wurde grundlegend \u00fcberarbeitet:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Statt \u00fcber <code>new<\/code> und den Konstruktor wird ein <code>StructuredTaskScope<\/code> nun \u00fcber die statische Factory-Methode <code>StructuredTaskScope.open()<\/code> ge\u00f6ffnet.<\/li>\n\n\n\n<li>Wird <code>open()<\/code> ohne Parameter aufgerufen, wird ein <code>StructuredTaskScope<\/code> erzeugt, der darauf wartet, dass <em>alle<\/em> Subtasks erfolgreich abgeschlossen sind ... oder <em>ein<\/em> Subtask fehlschl\u00e4gt \u2013 so wie zuvor die spezialisierte Implementierung <code>ShutdownOnFailure<\/code>. Aus <code>new StructuredTaskScope.ShutdownOnFailure()<\/code> wird somit <code>StructuredTaskScope.open()<\/code>.<\/li>\n\n\n\n<li>Andere Strategien werden nicht mehr durch Ableiten von <code>StructuredTaskScope<\/code> erzeugt, sondern durch einen sogenannten <em>Joiner<\/em>, der als Parameter an die <code>open()<\/code>-Methode \u00fcbergeben wird.<\/li>\n\n\n\n<li>Das <code>Joiner<\/code>-Interface definiert statische Factory-Methoden, um Joiner f\u00fcr h\u00e4ufig ben\u00f6tigte Strategien zu erzeugen.<\/li>\n\n\n\n<li><code>Joiner.anySuccessfulResultOrThrow()<\/code> erzeugt einen Joiner, der ein Ergebnis zur\u00fcckliefert, sobald der erste Subtask erfolgreich ist \u2013 so wie bisher die spezialisierte <code>StructuredTaskScope<\/code>-Implementierung <code>ShutdownOnSuccess<\/code>. Aus new <code>StructuredTaskScope.ShutdownOnSuccess()<\/code> wird somit <code>StructuredTaskScope.open(Joiner.anySuccessfulResultOrThrow())<\/code>.<\/li>\n\n\n\n<li>Eigene Join-Strategien k\u00f6nnen durch Implementierung des <code>Joiner<\/code>-Interfaces implementiert werden anstatt durch Erweiterung von <code>StructuredTaskScope<\/code>.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Zudem wurde der Abschluss der Verarbeitung vereinfacht:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Die Methode <code>StructuredTaskScope.result()<\/code> wurde entfernt \u2013 nun liefert <code>StructuredTaskScope.join()<\/code> das Ergebnis zur\u00fcck. Aus beispielsweise <code>scope.join(); return scope.result();<\/code> wird somit <code>return scope.join();<\/code><\/li>\n\n\n\n<li>Ebenso wurde die Methode <code>StructuredTaskScope.throwIfFailed()<\/code> entfernt \u2013 im Falle einer Exception wird diese nun ebenfalls von <code>StructuredTaskScope.join()<\/code> geworfen. Das macht die Fehlerbehandlung robuster.<\/li>\n\n\n\n<li><code>StructuredTaskScope.join()<\/code> wirft im Falle eines Fehlers nicht mehr eine generische <code>ExecutionException<\/code>, sondern eine Structured-Concurrency-spezifische <code>FailedException<\/code> oder eine <code>TimeoutException<\/code>.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Hier siehst du die \u00c4nderung noch mal am Beispiel der <code>race()<\/code>-Methode, die ich in einigen vorherigen Artikeln gezeigt habe:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Alte Implementierung bis Java 24:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-33\" 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;R&gt; <span class=\"hljs-function\">R <span class=\"hljs-title\">race<\/span><span class=\"hljs-params\">(Callable&lt;R&gt; task1, Callable&lt;R&gt; task2)<\/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> StructuredTaskScope.ShutdownOnSuccess&lt;R&gt;()) {\n        scope.fork(task1);\n        scope.fork(task2);\n        scope.join();\n        <span class=\"hljs-keyword\">return<\/span> scope.result();\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-33\"><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 class=\"wp-block-paragraph\">Neue Implementierung ab Java 25:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-34\" 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;R&gt; <span class=\"hljs-function\">R <span class=\"hljs-title\">race<\/span><span class=\"hljs-params\">(Callable&lt;R&gt; task1, Callable&lt;R&gt; task2)<\/span>\n        <span class=\"hljs-keyword\">throws<\/span> InterruptedException <\/span>{\n    Joiner&lt;R, R&gt; joiner = Joiner.anySuccessfulResultOrThrow();\n    <span class=\"hljs-keyword\">try<\/span> (<span class=\"hljs-keyword\">var<\/span> scope = StructuredTaskScope.open(joiner)) {\n        scope.fork(task1);\n        scope.fork(task2);\n        <span class=\"hljs-keyword\">return<\/span> scope.join();\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-34\"><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 class=\"wp-block-paragraph\">Durch diese \u00c4nderungen werden <code>StructuredTaskScope<\/code> und Join-Strategie entkoppelt, was zu flexiblerem und besser wartbarem Code f\u00fchrt (Stichwort: <a href=\"https:\/\/de.wikipedia.org\/wiki\/Komposition_an_Stelle_von_Vererbung\" target=\"_blank\" rel=\"noopener\">Composition over inheritance<\/a>).<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Beispiel: Die schnellste Antwort gewinnt<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Ein h\u00e4ufiges Szenario ist die parallele Abfrage mehrerer Dienste, bei der die erste g\u00fcltige Antwort verwendet werden soll \u2013 im folgenden Beispiel beim Einholen von Wetterdaten:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-35\" 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> <span class=\"hljs-keyword\">throws<\/span> InterruptedException <\/span>{\n    Joiner&lt;WeatherResponse, WeatherResponse&gt; joiner = Joiner.anySuccessfulResultOrThrow();\n    <span class=\"hljs-keyword\">try<\/span> (<span class=\"hljs-keyword\">var<\/span> scope = StructuredTaskScope.open(joiner)) {\n        scope.fork(() -&gt; weatherService.readFromStation1(location));\n        scope.fork(() -&gt; weatherService.readFromStation2(location));\n        scope.fork(() -&gt; weatherService.readFromStation3(location));\n        <span class=\"hljs-keyword\">return<\/span> scope.join();\n    }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-35\"><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 class=\"wp-block-paragraph\">Sobald eine der Aufgaben erfolgreich ist, werden die anderen automatisch abgebrochen. Die Methode <code>scope.join()<\/code> gibt das Ergebnis der ersten erfolgreichen Aufgabe zur\u00fcck oder wirft eine <code>FailedException<\/code>, falls keine Aufgabe erfolgreich abgeschlossen wurde.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ohne Structured Concurrency m\u00fcsstest du dieselbe Aufgabe mit deutlich mehr Code, manuellem Thread-Handling und eigener Fehlerlogik umsetzen \u2013 was nicht nur zeitaufwendiger, sondern auch wesentlich anf\u00e4lliger f\u00fcr Bugs w\u00e4re.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Fazit<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Mit <a href=\"https:\/\/openjdk.org\/jeps\/505\" target=\"_blank\" rel=\"noopener\">JEP 505<\/a> macht Structured Concurrency einen gro\u00dfen Schritt Richtung Finalisierung. Die \u00fcberarbeitete API ist klarer strukturiert, besser verst\u00e4ndlich und robuster in der Fehlerbehandlung.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Es zeigt sich einmal mehr, wie wertvoll das Feedback der Java-Community in der Preview-Phase eines Features ist: Nur durch R\u00fcckmeldungen aus der Praxis konnten die Schw\u00e4chen der bisherigen API erkannt und gezielt verbessert werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Eine ausf\u00fchrlichere Beschreibung und zahlreiche weitere Beispiele findest du im <a href=\"https:\/\/www.happycoders.eu\/de\/java\/structured-concurrency-structuredtaskscope\/\">Hauptartikel \u00fcber Structured Concurrency<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"primitive-types-in-patterns-instanceof-and-switch-third-preview-jep-507\">Primitive Types in Patterns, instanceof, and switch (Third Preview) \u2013 JEP 507<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Pattern Matching geh\u00f6rt zu den spannendsten Weiterentwicklungen der letzten Jahre. Was mit <em>Pattern Matching for instanceof<\/em> in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-16-features\/#pattern-matching-for-instanceof\">Java 16<\/a> begann und mit <em>Pattern Matching for switch<\/em> in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-21-features\/#pattern-matching-for-switch-jep-441\">Java 21<\/a> ausgeweitet wurde, wird nun erweitert \u2013 und zwar auf primitive Datentypen wie <code>int<\/code>, <code>double<\/code> oder <code>boolean<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bisher war Pattern Matching auf Referenztypen beschr\u00e4nkt. Also etwa so:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-36\" 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-36\"><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 class=\"wp-block-paragraph\">Mit primitiven Werten ging das nicht. Zwar konnte man schon lange primitive Werte wie z. B. <code>int<\/code> im klassischen <code>switch<\/code> mit Konstanten vergleichen \u2026<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-37\" 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\">404<\/span> -&gt; System.out.println(<span class=\"hljs-string\">\"Not Found\"<\/span>);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-37\"><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 class=\"wp-block-paragraph\">\u2026 aber das funktionierte nur mit <code>byte<\/code>, <code>short<\/code>, <code>char<\/code> und <code>int<\/code> \u2013 nicht jedoch mit <code>long<\/code>, <code>float<\/code>, <code>double<\/code> oder <code>boolean<\/code>. Und <code>instanceof<\/code> funktionierte mit primitiven Typen gar nicht.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Durch <em>Primitive Types in Patterns, instanceof, and switch<\/em> wird sich das \u00e4ndern:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Alle primitiven Typen (<code>int<\/code>, <code>long<\/code>, <code>float<\/code>, <code>double<\/code>, <code>char<\/code>, <code>byte<\/code>, <code>short<\/code>, <code>boolean<\/code>) lassen sich nun in <code>switch<\/code>-Anweisungen und -Ausdr\u00fccken verwenden \u2013 sowohl mit Konstanten als auch mit Pattern Matching.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Pattern Matching mit primitiven Typen ist nun auch mit <code>instanceof<\/code> m\u00f6glich.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">Was bedeutet Pattern Matching mit primitiven Typen genau?<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Beim Pattern Matching mit Referenztypen fragt man: \u201eIst dieses Objekt Instanz von Typ XY oder einer seiner Unterklassen?\u201c Bei primitiven Typen funktioniert das anders, denn hier gibt es keine Vererbung. Stattdessen wird gepr\u00fcft: L\u00e4sst sich der aktuelle Wert ohne Pr\u00e4zisionsverlust in einem bestimmten Zieltyp darstellen?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ein Beispiel:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-38\" 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    System.out.println(<span class=\"hljs-string\">\"b = \"<\/span> + b);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-38\"><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 class=\"wp-block-paragraph\">Hier matcht <code>i<\/code> auf das Pattern <code>byte b<\/code>, wenn der Wert auch in einem <code>byte<\/code> Platz findet. F\u00fcr <code>i = 100<\/code> w\u00e4re das der Fall, f\u00fcr <code>i = 500<\/code> nicht.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Oder bei Gleitkommazahlen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-39\" 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    System.out.println(<span class=\"hljs-string\">\"f = \"<\/span> + f);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-39\"><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 class=\"wp-block-paragraph\">Hier gilt: Nur wenn <code>d<\/code> ohne Pr\u00e4zisionsverlust in einen <code>float<\/code> passt, matcht das Pattern. F\u00fcr <code>d = 1.5<\/code> klappt das, f\u00fcr <code>d = Math.PI<\/code> oder <code>d = 16.777.217<\/code> hingegen nicht. Beide Zahlen sind zu pr\u00e4zise, um in einer 32-Bit-<code>float<\/code>-Variablen gespeichert zu werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Du kannst \u2013 wie bei Referenztypen \u2013 zus\u00e4tzliche Bedingungen anh\u00e4ngen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-40\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">int<\/span> a = ...\n<span class=\"hljs-keyword\">if<\/span> (a <span class=\"hljs-keyword\">instanceof<\/span> <span class=\"hljs-keyword\">byte<\/span> b &amp;&amp; b &gt; <span class=\"hljs-number\">0<\/span>) {\n    System.out.println(<span class=\"hljs-string\">\"b = \"<\/span> + b);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-40\"><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 class=\"wp-block-paragraph\">In diesem Fall matcht das Pattern nur, wenn <code>a<\/code> sich verlustfrei als <code>byte<\/code> darstellen l\u00e4sst und der Wert zus\u00e4tzlich gr\u00f6\u00dfer als 0 ist.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Pattern Matching mit switch und primitiven Typen<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Das Ganze funktioniert nicht nur mit <code>instanceof<\/code>, sondern auch mit <code>switch<\/code>. Hier ein vollst\u00e4ndiges Beispiel:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-41\" 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-41\"><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 class=\"wp-block-paragraph\">Abh\u00e4ngig vom konkreten Wert wird jeweils der erste passende Fall ausgef\u00fchrt:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>F\u00fcr <code>value = 42<\/code> beispielsweise matcht das Pattern <code>byte b<\/code>, weil sich der Wert ohne Informationsverlust als <code>byte<\/code> speichern l\u00e4sst.<\/li>\n\n\n\n<li>F\u00fcr <code>value = 200<\/code> passt <code>byte<\/code> nicht mehr, aber <code>short<\/code> sehr wohl \u2013 also wird der <code>short s<\/code>-Zweig ausgef\u00fchrt.<\/li>\n\n\n\n<li>F\u00fcr <code>value = 65000<\/code> greift <code>short<\/code> ebenfalls nicht mehr, aber <code>char c<\/code>, da <code>char<\/code> Werte von 0 bis 65.535 abbilden kann.<\/li>\n\n\n\n<li>F\u00fcr <code>value = 500000<\/code> sind <code>byte<\/code>, <code>short<\/code> und <code>char<\/code> zu klein \u2013 hier passt <code>int i<\/code>.<\/li>\n\n\n\n<li>F\u00fcr <code>value = 3.14<\/code> ist keine Ganzzahl-Darstellung m\u00f6glich, aber der Wert passt ohne Genauigkeitsverlust in einen <code>float<\/code>, also wird der Branch hinter <code>float f<\/code> ausgef\u00fchrt.<\/li>\n\n\n\n<li>F\u00fcr <code>value = Math.PI<\/code> bleibt nur noch <code>double d<\/code>, da <code>Math.PI<\/code> f\u00fcr <code>float<\/code> zu pr\u00e4zise ist.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Wie bei Objekttypen gilt auch hier: Du musst alle F\u00e4lle abdecken oder einen <code>default<\/code>-Branch angeben, um eine vollst\u00e4ndige (exhaustive) Pr\u00fcfung sicherzustellen.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Feinheiten: Dominanz und Vollst\u00e4ndigkeit<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Auch bei primitiven Typen spielt das Prinzip der <em>Dominanz<\/em> eine wichtige Rolle: Ein <code>int<\/code>-Wert passt grunds\u00e4tzlich auch in einen <code>long<\/code>, daher w\u00fcrde ein Pattern <code>long l<\/code> alle int-Werte ebenfalls abfangen \u2013 und darf daher nicht vor einem Pattern <code>int i<\/code> im Code stehen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Zus\u00e4tzlich gilt \u2013 wie bei allen modernen <code>switch<\/code>-Features \u2013 die Regel der Vollst\u00e4ndigkeit: Der <code>switch<\/code>-Block muss alle theoretisch m\u00f6glichen F\u00e4lle abdecken. Falls das nicht m\u00f6glich oder nicht sinnvoll ist, musst du einen <code>default<\/code>-Zweig definieren, um Compiler-Fehler zu vermeiden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Mehr zu den genauen Regeln f\u00fcr Dominanz und Exhaustiveness sowie weitere Beispiele und Besonderheiten 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<h4 class=\"wp-block-heading\">R\u00fcckblick<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Primitive Types in Patterns, instanceof, and switch wurde 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 JEP 455 eingef\u00fchrt und in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-24-features\/#primitive-types-in-patterns-instanceof-and-switch-second-preview-jep-488\">Java 24<\/a> durch JEP 488 ohne \u00c4nderungen als Preview wiedervorgestellt. In Java 25 geht es nun, spezifiziert durch <a href=\"https:\/\/openjdk.org\/jeps\/507\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 507<\/a>, in die dritte Preview-Runde \u2013 erneut ohne \u00c4nderungen, um weiteres Feedback der Java-Community einzuholen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"vector-api-tenth-incubator-jep-508\">Vector API (Tenth Incubator) \u2013 JEP 508<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Die Vector API wird mit Java 25 bereits zum zehnten Mal im Incubator-Stadium vorgestellt \u2013 spezifiziert durch <a href=\"https:\/\/openjdk.org\/jeps\/508\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 508<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die API erm\u00f6glicht es, mathematische Vektoroperationen wie die folgende besonders effizient auszuf\u00fchren:<\/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\" \/><figcaption class=\"wp-element-caption\">Beispiel einer Vektoraddition<\/figcaption><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">Die JVM kann diese Operationen so abbilden, dass sie \u2013 je nach Vektorgr\u00f6\u00dfe \u2013 direkt auf die Vektor-Instruktionss\u00e4tze moderner CPUs zugreifen. In vielen F\u00e4llen l\u00e4sst sich eine solche Berechnung dadurch in einem einzigen CPU-Zyklus ausf\u00fchren.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die Vector API bleibt ein Incubator-Feature bis die von ihr ben\u00f6tigten Bausteine aus <a href=\"https:\/\/openjdk.org\/projects\/valhalla\/\" target=\"_blank\" rel=\"noopener\">Project Valhalla<\/a> das Preview-Stadium erreicht haben. Sobald die Vector API in einer ersten Preview-Version vorliegt, werde ich sie ausf\u00fchrlich und mit Praxisbeispielen beschreiben.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"sonstige-aenderungen-in-java-25\">Sonstige \u00c4nderungen in Java 25<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In diesem Abschnitt findest du \u00c4nderungen, die sich nicht in die anderen Kapitel einsortieren lie\u00dfen. Es handelt sich dabei um weniger prominente JEPs, um Entfernungen und um einige (von mir aus den Release Notes ausgew\u00e4hlte) kleinere \u00c4nderungen, die ohne JEP umgesetzt wurden.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"key-derivation-function-api-jep-510\">Key Derivation Function API \u2013 JEP 510<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Mit einer <em>Key Derivation Function<\/em> (KDF) lassen sich aus einem geheimen Eingabewert \u2013 etwa einem Passwort, einer Passphrase oder einem bestehenden Schl\u00fcssel \u2013 weitere kryptographische Schl\u00fcssel ableiten.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Damit KDFs konsistent genutzt und von Sicherheitsanbietern implementiert werden k\u00f6nnen, bedarf es einer standardisierten Schnittstelle. Genau das liefert <a href=\"https:\/\/openjdk.org\/jeps\/510\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 510<\/a> mit der Key Derivation Function API und der Klasse <code>javax.crypto.KDF<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\u00dcber diese API kannst du verschiedene KDF-Algorithmen laden und verwenden. Im folgenden Beispiel nutzen wir \u201eHKDF-SHA256\u201c, um aus einem Passwort und einem Salt einen AES-Schl\u00fcssel abzuleiten:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-42\" 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    KDF hkdf = KDF.getInstance(<span class=\"hljs-string\">\"HKDF-SHA256\"<\/span>);\n\n    AlgorithmParameterSpec params =\n           HKDFParameterSpec.ofExtract()\n                  .addIKM(<span class=\"hljs-string\">\"the super secret passphrase\"<\/span>.getBytes(StandardCharsets.UTF_8))\n                  .addSalt(<span class=\"hljs-string\">\"the salt\"<\/span>.getBytes(StandardCharsets.UTF_8))\n                  .thenExpand(<span class=\"hljs-string\">\"my derived key\"<\/span>.getBytes(StandardCharsets.UTF_8), <span class=\"hljs-number\">32<\/span>);\n\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-42\"><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 class=\"wp-block-paragraph\">Falls du dich \u00fcber die kompakte <code>main()<\/code>-Methode wunderst: Diese ist Teil der Neuerungen, die im Abschnitt <a href=\"#compact-source-files-and-instance-main-methods-jep-512\">Compact Source Files and Instance Main Methods<\/a> behandelt werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Erkl\u00e4rungen zu den im Code vorkommenden Abk\u00fcrzungen findest du in den folgenden Wikipedia-Artikeln:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>HKDF<\/strong> steht f\u00fcr \u201e<a href=\"https:\/\/en.wikipedia.org\/wiki\/HKDF\" target=\"_blank\" rel=\"noopener\">HMAC-based Key Derivation Function<\/a>\u201c.<\/li>\n\n\n\n<li><strong>HMAC<\/strong> bedeutet \u201e<a href=\"https:\/\/de.wikipedia.org\/wiki\/HMAC\" target=\"_blank\" rel=\"noopener\">Hash-based Message Authentication Code<\/a>\u201c.<\/li>\n\n\n\n<li><strong>IKM<\/strong> bezeichnet das \u201einput key material\u201c, also z.\u202fB. das Passwort.<\/li>\n\n\n\n<li><strong>AES<\/strong> ist der \u201e<a href=\"https:\/\/de.wikipedia.org\/wiki\/Advanced_Encryption_Standard\" target=\"_blank\" rel=\"noopener\">Advanced Encryption Standard<\/a>\u201c, ein verbreiteter Verschl\u00fcsselungsalgorithmus.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Wenn du das Beispiel ausf\u00fchrst, solltest du folgende Ausgabe erhalten:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-43\" 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-43\"><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 class=\"wp-block-paragraph\">Der so erzeugte Schl\u00fcssel l\u00e4sst sich beispielsweise als Session Key f\u00fcr eine sichere Daten\u00fcbertragung einsetzen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die Key Derivation Function API wurde in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-24-features\/#key-derivation-function-api-preview-jep-478\">Java 24<\/a> erstmals als Preview-Feature eingef\u00fchrt und ist ab Java 25 nun fester Bestandteil des JDK, ohne \u00c4nderungen gegen\u00fcber der Preview-Version.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"remove-the-32-bit-x86-port-jep-503\">Remove the 32-bit x86 Port \u2013 JEP 503<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Nachdem in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-24-features\/#remove-the-windows-32-bit-x86-port-jep-479\">Java 24<\/a> der 32-Bit-Port f\u00fcr Windows entfernt wurde, wird in Java 25 durch <a href=\"https:\/\/openjdk.org\/jeps\/503\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 503<\/a> auch die letzte verbleibende 32-Bit-Variante \u2013 die f\u00fcr Linux \u2013 vollst\u00e4ndig entfernt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So wird der Extraaufwand f\u00fcr das Entwickeln und Testen der 32-Bit-Portierungen eliminiert, und die JDK-Developer k\u00f6nnen sich voll und ganz auf neue Features fokussieren.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"relax-string-creation-requirements-in-stringbuilder-and-stringbuffer\">Relax String Creation Requirements in StringBuilder and StringBuffer<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Die Spezifikationen der <code>substring()<\/code>-, <code>subSequence()<\/code>- und <code>toString()<\/code>-Methoden der Klassen <code>StringBuilder<\/code> und <code>StringBuffer<\/code> erforderten bisher, dass immer ein neu erstelltes <code>String<\/code>-Objekt zur\u00fcckgegeben wird. Diese Anforderung wurde aus der Spezifikation entfernt, so dass diese Methoden nun z. B. f\u00fcr einen leeren String eine <code>\"\"<\/code>-Konstante zur\u00fcckgeben k\u00f6nnen, was schneller ist, als einen neuen leeren String zu erzeugen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr diese \u00c4nderung gibt es keinen JEP; sie wird im Bug-Tracker unter <a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8138614\" target=\"_blank\" rel=\"noopener\">JDK-8138614<\/a> aufgef\u00fchrt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"new-methods-on-bodyhandlers-and-bodysubscribers-to-limit-the-number-of-response-body-bytes-accepted-by-the-httpclient\">New Methods on BodyHandlers and BodySubscribers To Limit The Number of Response Body Bytes Accepted By The HttpClient<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Die Klassen <code>java.net.http.HttpResponse.BodyHandlers<\/code> und <code>java.net.http.HttpResponse.BodySubscribers<\/code> wurden um je eine <code>limiting()<\/code>-Methode erweitert, mit der die Gr\u00f6\u00dfe einer Antwort auf eine HTTP-Anfrage begrenzt werden kann.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr diese \u00c4nderung gibt es keinen JEP; sie wird im Bug-Tracker unter <a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8328919\" target=\"_blank\" rel=\"noopener\">JDK-8328919<\/a> aufgef\u00fchrt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"the-usecompressedclasspointers-option-is-deprecated\">The UseCompressedClassPointers Option is Deprecated<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Standardm\u00e4\u00dfig arbeitet die JVM mit <a href=\"https:\/\/www.happycoders.eu\/de\/java\/object-headers-compressed-class-pointers\/#compressed-class-pointers\">Compressed Class Pointers<\/a> \u2013 das sind auf 32 Bit komprimierte Pointer im Objekt-Header, die auf die zum Objekt geh\u00f6rige Klassendatenstruktur zeigen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bevor Compressed Class Pointers eingef\u00fchrt wurden, waren diese Pointer auf 64-Bit-Systemen 64 Bit lang. Dieser Modus l\u00e4sst sich aktuell noch durch <code>-XX:-UseCompressedClassPointers<\/code> reaktivieren. Das ist allerdings faktisch irrelevant, denn 32-Bit-Pointer reichen aus, um 4 GB und damit ca. 6 Millionen Klassen zu addressieren. Selbst gro\u00dfe Java-Anwendungen z\u00e4hlen selten mehr als 100.000 Klassen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Durch die in Java 25 produktiv geschalteten <a href=\"#compact-object-headers-jep-519\">Compact Object Headers<\/a> werden Class Pointer weiter komprimiert auf nur 22 Bit, womit sich ca. 4 Millionen \u2013 also immer noch ausreichend \u2013 Klassen adressieren lassen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Der Support f\u00fcr unkomprimierte Klassenpointer wird <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-27-features\/#obsolete-usecompressedclasspointers\">in Java 27 entfernt<\/a> werden. Entsprechend wurde die Option <code>UseCompressedClassPointers<\/code> in Java 25 als <em>deprecated<\/em> markiert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr diese \u00c4nderung gibt es keinen JEP; sie wird im Bug-Tracker unter <a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8350753\" target=\"_blank\" rel=\"noopener\">JDK-8350753<\/a> aufgef\u00fchrt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"various-permission-classes-deprecated-for-removal\">Various Permission Classes Deprecated for Removal<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-17-features\/#deprecate-the-security-manager-for-removal\">Java 17<\/a> wurde der Security Manager <em>deprecated for removal<\/em> gekennzeichnet. Seit <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-24-features\/#permanently-disable-the-security-manager-jep-486\">Java 24<\/a> kann der Security Manager nicht mehr aktiviert werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In Java 25 wurden nun zahlreiche <code>...Permission<\/code>-Klassen, die nur im Zusammenhang mit dem Security Manager verwendbar waren, ebenfalls als <em>deprecated for removal<\/em> markiert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Welche Klassen das im Detail sind, kannst du im Bug-Tracker unter <a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8348967\" target=\"_blank\" rel=\"noopener\">JDK-8348967<\/a>, <a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8353641\" target=\"_blank\" rel=\"noopener\">JDK-8353641<\/a>, <a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8353642\" target=\"_blank\" rel=\"noopener\">JDK-8353642<\/a> und <a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8353856\" target=\"_blank\" rel=\"noopener\">JDK-8353856<\/a> nachlesen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"syntax-highlighting-for-code-fragments\">Syntax Highlighting for Code Fragments<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Das <code>javadoc<\/code>-Tool wurde um die Kommandozeilenoption <code>--syntax-highlight<\/code> erweitert. Wird diese beim Aufruf des <code>javadoc<\/code>-Kommandos angegeben, wird die Library <a href=\"https:\/\/github.com\/highlightjs\/highlight.js\" target=\"_blank\" rel=\"noopener\">Highlight.js<\/a> in die generierte Dokumentation eingebunden und der Code in <code>{@snippet}<\/code> tags und HTML-Elementen entsprechend farblich gekennzeichnet.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr diese \u00c4nderung gibt es keinen JEP; sie wird im Bug-Tracker unter <a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8348282\" target=\"_blank\" rel=\"noopener\">JDK-8348282<\/a> aufgef\u00fchrt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"keyboard-navigation\">Keyboard Navigation<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Mit Java 25 generierte JavaDoc-Dokumentation l\u00e4sst sich nun mit der Tastatur navigieren: <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>\/<\/code> fokussiert das Suchfeld oben rechts.<\/li>\n\n\n\n<li><code>.<\/code> fokussiert das Filterfeld in der Sidebar.<\/li>\n\n\n\n<li><code>Esc<\/code> entfernt den Fokus aus dem Such- oder Filterfeld.<\/li>\n\n\n\n<li>Mit <code>Tab<\/code> und den Pfeiltasten kannst du in der Sidebar und den Suchergebnissen navigieren.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr diese \u00c4nderung gibt es keinen JEP; sie wird im Bug-Tracker unter <a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8350638\" target=\"_blank\" rel=\"noopener\">JDK-8350638<\/a> aufgef\u00fchrt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"add-standard-system-property-stdin-encoding\">Add Standard System Property stdin.encoding<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\u00dcber die neue System Property <code>stdin.encoding<\/code> kann der Zeichensatz f\u00fcr das Lesen von <code>System.in<\/code> festgelegt werden. Wenn nicht explizit angegeben \u2013 z. B. durch <code>-Dstdin.encoding=UTF-8<\/code> \u2013, wird der Wert durch das Betriebssystem und die Benutzerumgebung ermittelt. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Beachte, dass diese Einstellung nicht automatisch verwendet wird, sondern explizit von einer Anwendung ausgelesen und angewendet werden muss, z. B. bei Verwendung von <code>InputStreamReader<\/code> oder <code>Scanner<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr diese \u00c4nderung gibt es keinen JEP; sie wird im Bug-Tracker unter <a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8350703\" target=\"_blank\" rel=\"noopener\">JDK-8350703<\/a> aufgef\u00fchrt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"the-jwebserver-tool-d-command-line-option-now-accepts-directories-specified-with-a-relative-path\">The jwebserver Tool -d Command Line Option Now Accepts Directories Specified With a Relative Path<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-18-features\/#simple-web-server\">Java 18<\/a> wurde der sogenannte <em>Simple Web Server<\/em> eingef\u00fchrt \u2013 ein rudiment\u00e4rer HTTP-Server, der schnell hochgefahren werden kann, um statische Webseiten auszuliefern.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Das folgende Kommando z. B. liefert das <code>\/tmp<\/code>-Verzeichnis an IP-Adresse 127.0.0.100 und Port 4444 aus:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-44\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">jwebserver -b 127.0.0.100 -p 4444 -d \/tmp<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-44\"><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 class=\"wp-block-paragraph\">Dabei musste (\u00fcber den Parameter <code>-d<\/code>) bisher immer ein <em>absoluter<\/em> Pfad angegeben werden \u2013 umst\u00e4ndlich, wenn man innerhalb des aktuellen Projekts ein Verzeichnis per HTTP freigeben m\u00f6chte. Ab Java 25 darf nun auch ein <em>relativer<\/em> Verzeichnisname angegeben werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr diese \u00c4nderung gibt es keinen JEP; sie wird im Bug-Tracker unter <a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8355360\" target=\"_blank\" rel=\"noopener\">JDK-8355360<\/a> aufgef\u00fchrt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"java-io-file-treats-the-empty-pathname-as-the-current-user-directory\">java.io.File treats the empty pathname as the current user directory<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Ein mit <code>new File(\"\")<\/code> erzeugtes <code>java.io.File<\/code>-Objekt f\u00fchrte bisher zu undefiniertem und inkonsistentem Verhalten beim Aufruf von Methoden auf diesem Objekt. Ab Java 25 wird damit ein <code>File<\/code>-Objekt erzeugt, das das aktuelle Verzeichnis repr\u00e4sentiert. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Damit wird das Verhalten von File an <code>java.nio.Path<\/code> angepasst \u2013 <code>Path.of(\"\")<\/code> erzeugte schon immer eine Repr\u00e4sentation des aktuellen Verzeichnisses.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr diese \u00c4nderung gibt es keinen JEP; sie wird im Bug-Tracker unter <a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8024695\" target=\"_blank\" rel=\"noopener\">JDK-8024695<\/a> aufgef\u00fchrt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"java-io-file-delete-no-longer-deletes-read-only-files-on-windows\">java.io.File.delete no longer deletes read-only files on Windows<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Bisher konnte man durch einen Aufruf von <code>File.delete()<\/code> unter Windows auch solche Dateien l\u00f6schen, die als \u201eRead-only\u201c markiert waren. Ab Java 25 werden solche Dateien nicht mehr gel\u00f6scht, und <code>delete()<\/code> gibt entsprechend <code>false<\/code> zur\u00fcck.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Das bisherige Verhalten kann mit der System Property <code style=\"white-space: nowrap;\">-Djdk.io.File.allowDeleteReadOnlyFiles=true<\/code> wiederhergestellt werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">F\u00fcr diese \u00c4nderung gibt es keinen JEP; sie wird im Bug-Tracker unter <a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8355954\" target=\"_blank\" rel=\"noopener\">JDK-8355954<\/a> aufgef\u00fchrt.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"vollstaendige-liste-aller-aenderungen-in-java-25\">Vollst\u00e4ndige Liste aller \u00c4nderungen in Java 25<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In diesem Artikel habe ich dir alle JDK Enhancement Proposals (JEPs) sowie eine Auswahl weiterer \u00c4nderungen ohne JEP vorgestellt, die in Java 25 umgesetzt wurden. Eine vollst\u00e4ndige Auflistung aller \u00c4nderungen findest du in den <a href=\"https:\/\/www.oracle.com\/java\/technologies\/javase\/25all-relnotes.html\" target=\"_blank\" rel=\"noopener\">Java 25 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 class=\"wp-block-paragraph\">Java 25 ist wieder einmal ein rundum gelungenes LTS (Long-Term-Support) Release.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Mit <em>Scoped Values<\/em> ist das zweite Feature aus Project Loom finalisiert worden. Schade, dass es <em>Structured Concurrency<\/em> nicht in dieses Release geschafft hat \u2013 aber dank des 6-monatigen Release-Zyklus bekommen wir lieber etwas sp\u00e4ter ein ausgereiftes Feature als zu fr\u00fch ein unausgereiftes.<\/li>\n\n\n\n<li><em>Module Import Declarations<\/em> machen den Import-Block \u00fcbersichtlicher \u2013 es bleibt abzuwarten, inwieweit dies (au\u00dferhalb von JShell und kompakten Quelldateien) angenommen wird \u2013 k\u00fcmmert sich doch heutzutage in erster Linie die IDE um die Verwaltung der Imports.<\/li>\n\n\n\n<li><em>Compact Source Files and Instance Main Methods<\/em> lassen uns schneller kurze Test- und Demoprogramme schreiben. Sie sollen au\u00dferdem das Erlernen der Sprache f\u00fcr Einsteiger:innen vereinfachen.<\/li>\n\n\n\n<li><em>Flexible Constructor Bodies<\/em> erlauben uns endlich, in Konstruktoren Code auch vor dem Aufruf von <code>super()<\/code> oder <code>this()<\/code> aufzurufen und machen damit unsch\u00f6ne Workarounds, z. B. zur \u00dcberpr\u00fcfung von Parametern vor dem Aufruf des Super-Konstruktors hinf\u00e4llig.<\/li>\n\n\n\n<li><em>Compact Object Headers<\/em> reduzieren den Objekt-Header von 12 auf 8 Byte und reduzieren damit den Memory-Footprint insbesondere von Anwendungen mit vielen kleinen Objekten.<\/li>\n\n\n\n<li><em>Generational Shenandoah<\/em> beschleunigt Anwendungen, die den Shenandoah Garbage Collector einsetzen. Konkrete Zahlen werden allerdings in den JEPs nicht genannt.<\/li>\n\n\n\n<li><em>Ahead-of-Time Command-Line Ergonomics<\/em> vereinfachen die Erstellung eines AOT-Caches, und durch <em>Ahead-of-Time Method Profiling<\/em> werden auch Informationen \u00fcber Methodenaufrufe im AOT-Cache gespeichert, was zu deutlichen Verbesserungen der Startzeit f\u00fchren kann, da so h\u00e4ufig aufgerufene Methoden sofort optimiert werden k\u00f6nnen.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Weitere kleinere \u00c4nderungen runden das LTS-Release wie immer ab. Du kannst Java 25 <a href=\"https:\/\/jdk.java.net\/25\/\" target=\"_blank\" rel=\"noopener\">hier<\/a> herunterladen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Auf welches Java-25-Feature freust du dich am meisten? Schreib es in die Kommentare!<\/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 neuen 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>Java 25: Scoped Values, Compact Source Files, Flexible Constructor Bodies, Compact Object Headers und mehr \u2013 verst\u00e4ndlich erkl\u00e4rt, mit Beispielen.<\/p>\n","protected":false},"author":1,"featured_media":51535,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_seopress_titles_title":"","_seopress_titles_desc":"","_seopress_robots_index":"","_seopress_robots_follow":"","_seopress_robots_imageindex":"","_seopress_robots_snippet":"","_seopress_robots_primary_cat":"","_seopress_robots_breadcrumbs":"","_seopress_robots_freeze_modified_date":"","_seopress_robots_custom_modified_date":"","_seopress_robots_canonical":"","_seopress_social_fb_title":"","_seopress_social_fb_desc":"","_seopress_social_fb_img":"","_seopress_social_fb_img_attachment_id":0,"_seopress_social_fb_img_width":0,"_seopress_social_fb_img_height":0,"_seopress_social_twitter_title":"","_seopress_social_twitter_desc":"","_seopress_social_twitter_img":"","_seopress_social_twitter_img_attachment_id":0,"_seopress_social_twitter_img_width":0,"_seopress_social_twitter_img_height":0,"_seopress_redirections_value":"","_seopress_redirections_enabled":"","_seopress_redirections_enabled_regex":"","_seopress_redirections_logged_status":"","_seopress_redirections_param":"","_seopress_redirections_type":0,"_seopress_analysis_target_kw":"java 25 features","_seopress_news_disabled":"","_seopress_video_disabled":"","_seopress_video":[],"_seopress_pro_schemas_manual":[],"_seopress_pro_rich_snippets_disable_all":"","_seopress_pro_rich_snippets_disable":[],"_seopress_pro_schemas":[],"_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":63583,"_post_count":0,"footnotes":""},"categories":[64],"tags":[176],"class_list":["post-51163","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\/2025\/05\/java-25-feature-image-v3.jpg",1536,853,false],"thumbnail":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/05\/java-25-feature-image-v3.jpg",150,83,false],"medium":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/05\/java-25-feature-image-v3.jpg",300,167,false],"medium_large":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/05\/java-25-feature-image-v3.jpg",768,427,false],"large":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/05\/java-25-feature-image-v3.jpg",1024,569,false],"feature_thumb_224":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/05\/java-25-feature-image-v3-224x124.jpg",224,124,true],"feature_thumb_336":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/05\/java-25-feature-image-v3-336x187.jpg",336,187,true],"feature_thumb_504":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/05\/java-25-feature-image-v3-504x280.jpg",504,280,true],"feature_thumb_672":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/05\/java-25-feature-image-v3-672x373.jpg",672,373,true],"half_400":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/05\/java-25-feature-image-v3-400x222.jpg",400,222,true],"half_600":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/05\/java-25-feature-image-v3-600x333.jpg",600,333,true],"full_800":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/05\/java-25-feature-image-v3-800x444.jpg",800,444,true],"full_944":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/05\/java-25-feature-image-v3-944x524.jpg",944,524,true],"full_1200":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/05\/java-25-feature-image-v3-1200x666.jpg",1200,666,true],"wide_1180":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/05\/java-25-feature-image-v3-1180x490.jpg",1180,490,true],"wide_1770":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/05\/java-25-feature-image-v3-1536x735.jpg",1536,735,true],"1536x1536":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/05\/java-25-feature-image-v3.jpg",1536,853,false],"2048x2048":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2025\/05\/java-25-feature-image-v3.jpg",1536,853,false]},"uagb_author_info":{"display_name":"Sven Woltmann","author_link":"https:\/\/www.happycoders.eu\/de\/author\/sven\/"},"uagb_comment_info":0,"uagb_excerpt":"Java 25: Scoped Values, Compact Source Files, Flexible Constructor Bodies, Compact Object Headers und mehr \u2013 verst\u00e4ndlich erkl\u00e4rt, mit Beispielen.","public_identification_id":"0e5208225eda49df9d7b3855c173fdd8","private_identification_id":"480468f292254c85b6ee9ecaefd6f6e4","_links":{"self":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/51163","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=51163"}],"version-history":[{"count":22,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/51163\/revisions"}],"predecessor-version":[{"id":56900,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/51163\/revisions\/56900"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/media\/51535"}],"wp:attachment":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/media?parent=51163"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/categories?post=51163"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/tags?post=51163"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}