{"id":24522,"date":"2021-11-22T14:45:00","date_gmt":"2021-11-22T13:45:00","guid":{"rendered":"https:\/\/www.happycoders.eu\/?p=24522"},"modified":"2026-04-15T15:00:06","modified_gmt":"2026-04-15T13:00:06","slug":"java-15-features","status":"publish","type":"post","link":"https:\/\/www.happycoders.eu\/de\/java\/java-15-features\/","title":{"rendered":"Java 15 Features (mit Beispielen)"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Java 15 brachte uns am 15. September 2020 mit \"Text Blocks\" die dritte Sprachverbesserung aus <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/projects\/amber\/\" target=\"_blank\">Project Amber<\/a> (nach <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-10-features\/#Local-Variable_Type_Inference_var\">\"var\" in Java 10<\/a> und <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-14-features\/#Switch_Expressions_Standard\">\"Switch Expressions\" in Java 14<\/a>) \u2013 und mit ZGC und Shenandoah zwei neue, auf sehr kurze Pausen optimierte Garbage Collectoren.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Doch das ist l\u00e4ngst nicht alles: Insgesamt 14 JDK Enhancement Proposals (JEPs) haben es in dieses Release geschafft.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ich habe die \u00c4nderungen wie immer nach Relevanz f\u00fcr die t\u00e4gliche Programmierarbeit sortiert. Nach den bereits genannten Features folgen Erweiterungen der JDK-Klassenbibliothek, Performance-\u00c4nderungen, experimentelle, Preview- und Incubator-Features, Deprecations und L\u00f6schungen und zuletzt sonstige \u00c4nderungen, mit denen wir eher selten in Ber\u00fchrung kommen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ich verwende wie immer die englischen Bezeichnungen der JEPs. Diese auf deutsch zu \u00fcbersetzen w\u00fcrde keinen Mehrwert bringen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"text-blocks\">Text Blocks<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Wenn wir bisher in Java einen mehrzeiligen String definieren wollten, sah das in etwa so aus:<\/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\">String sql =\n    <span class=\"hljs-string\">\"  SELECT id, title, text\\n\"<\/span>\n        + <span class=\"hljs-string\">\"    FROM Article\\n\"<\/span>\n        + <span class=\"hljs-string\">\"   WHERE category = \\\"Java\\\"\\n\"<\/span>\n        + <span class=\"hljs-string\">\"ORDER BY title\"<\/span>;<\/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\">Ab Java 15 k\u00f6nnen wir diesen String als \"Text Block\" notieren:<\/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\">String sql = <span class=\"hljs-string\">\"\"<\/span><span class=\"hljs-string\">\"\n      SELECT id, title, text\n        FROM Article\n       WHERE category = \"<\/span>Java<span class=\"hljs-string\">\"\n    ORDER BY title\"<\/span><span class=\"hljs-string\">\"\"<\/span>;<\/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\">Wie genau man Text Blocks schreibt und formatiert, welche Escape-Sequenzen wir nicht mehr ben\u00f6tigen ... und welche wir stattdessen zur Verf\u00fcgung haben, erf\u00e4hrst du im Hauptartikel <a href=\"\/de\/java\/java-text-blocks\/\">\"Java Text Blocks\"<\/a>.  <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">(<em>Text Blocks wurden erstmal als Preview-Feature <a href=\"\/de\/java\/java-13-features\/#Text_Blocks_Preview\">in Java 13<\/a> vorgestellt. Sie waren ein Ersatz f\u00fcr den von der Community nicht akzeptierten und daraufhin zur\u00fcckgezogenen <a href=\"https:\/\/openjdk.org:443\/jeps\/326\" target=\"_blank\" rel=\"noopener\">JEP 326, \"Raw String Literals\"<\/a>. Im zweiten Preview wurden in <a href=\"\/de\/java\/java-14-features\/#Text_Blocks_Second_Preview\">Java 14<\/a> zwei neue Escape-Sequenzen hinzugef\u00fcgt. Aufgrund des positiven Feedbacks wurden Text Blocks in Java 15 mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/378\" target=\"_blank\">JDK Enhancement Proposal 378<\/a> ohne weitere \u00c4nderungen als produktionsreifes Feature ver\u00f6ffentlicht.)<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"neue-garbage-collectoren-zgc-shenandoah\">Neue Garbage Collectoren: ZGC + Shenandoah<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Die Anforderungen an moderne Applikationen werden immer anspruchsvoller. Bei einem Speicherbedarf von Gigabytes bis hin zu Terabytes sollen sie mitunter Antwortzeiten im einstelligen Millisekundenbereich erreichen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Herk\u00f6mmliche Garbage Collectoren (wie der Allrounder G1) mit Stop-the-World-Phasen von hundert Millisekunden und mehr sind f\u00fcr solche Anforderungen nicht optimal geeignet.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Mit dem Ziel die Stop-the-World-Pausen so gut es geht zu eliminieren (in dem ein Gro\u00dfteil der Arbeit parallel zur laufenden Anwendung erledigt wird), oder wenigstens auf wenige Millisekunden zu reduzieren, haben Oracle und RedHat zwei neue Garbage Collectoren entwickelt, die seit Java 11 bzw. 12 als Preview-Features mit ausgeliefert wurden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ab Java 15 sind sie bereit f\u00fcr den produktiven Einsatz und machen die Java-Plattform hoffentlich f\u00fcr noch mehr Entwicklerinnen und Entwickler attraktiv.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"zgc-a-scalable-low-latency-garbage-collector\">ZGC: A Scalable Low-Latency Garbage Collector<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Der Z Garbage Collector, kurz ZGC, verspricht Pausezeiten von 10 ms nicht zu \u00fcberschreiten und dabei den Gesamtdurchsatz der Anwendung um nicht mehr als 15 % gegen\u00fcber dem G1GC zu reduzieren (die Verringerung des Durchsatzes sind die Kosten f\u00fcr die niedrige Latenz).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">ZGC unterst\u00fctzt Heap-Gr\u00f6\u00dfen von 8 MB bis zu 16 TB.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die Pausenzeiten sind dabei unabh\u00e4ngig sowohl von der Heap-Gr\u00f6\u00dfe als auch von der Anzahl der \u00fcberlebenden Objekte.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Genau wie G1, basiert ZGC auf Regionen, ist <a href=\"\/de\/java\/java-14-features\/#NUMA-Aware_Memory_Allocation_for_G1\">NUMA-kompatibel<\/a>, und kann ungenutzten Speicher an das Betriebssystem zur\u00fcckgeben.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">ZGC l\u00e4sst sich au\u00dferdem mit einer \"weichen\" Heap-Obergrenze konfigurieren (VM-Option <code>-XX:SoftMaxHeapSize<\/code>): ZGC wird diese Grenze nur dann \u00fcberschreiten, wenn es zur Vermeidung eines <code>OutOfMemoryErrors<\/code> notwendig ist.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Aktiviert wird ZGC mit der folgenden VM-Option:<\/p>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\"><code>-XX:+UseZGC<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die detaillierte Funktionsweise von ZGC w\u00fcrde den Rahmen dieses Artikels sprengen. Du kannst sie im <a href=\"https:\/\/wiki.openjdk.org\/spaces\/zgc\/pages\/34668579\/Main\" target=\"_blank\" rel=\"noreferrer noopener\">ZGC-Wiki<\/a> nachlesen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>(Erstmals war ZGC als <a href=\"\/de\/java\/java-11-features\/#ZGC_A_Scalable_Low-Latency_Garbage_Collector_Experimental\">Preview in Java 11<\/a> enthalten. <a href=\"\/de\/java\/java-13-features\/#ZGC_Uncommit_Unused_Memory_Experimental\">In Java 13 kamen die Uncommit<\/a>- und <a href=\"\/de\/java\/java-13-features\/#Soft_Max_Heap_Size\">SoftMaxHeapSize-Funktion<\/a> hinzu. Seit <a href=\"\/de\/java\/java-14-features\/#ZGC_on_macOS_Windows_Experimental\">Java 14 ist ZGC auch f\u00fcr Windows und macOS<\/a> verf\u00fcgbar. Mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/377\" target=\"_blank\">JDK Enhancement Proposal 377<\/a> wurde ZGC in Java 15 f\u00fcr den produktiven Einsatz freigegeben.)<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"shenandoah-a-low-pause-time-garbage-collector\">Shenandoah: A Low-Pause-Time Garbage Collector<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Genau wie ZGC verspricht auch Shenandoah minimale Pausezeiten, unabh\u00e4ngig von der Heap-Gr\u00f6\u00dfe.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wie genau Shenandoah das erreicht, kannst du im <a href=\"https:\/\/wiki.openjdk.org\/spaces\/shenandoah\/pages\/25002018\/Main\" target=\"_blank\" rel=\"noreferrer noopener\">Shenandoah-Wiki<\/a> nachlesen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Aktivieren kannst du Shenandoah mit der folgenden VM-Option:<\/p>\n\n\n\n<p class=\"has-text-align-center wp-block-paragraph\"><code>-XX:+UseShenandoahGC<\/code><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Genau wie G1 und ZGC, gibt auch Shenandoah ungenutzten Speicherplatz nach einer Weile wieder an das Betriebssystem zur\u00fcck.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Support f\u00fcr NUMA und SoftMaxHeapSize gibt es aktuell nicht; zumindest NUMA-Support ist jedoch geplant.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>(Shenandoah ist <a href=\"\/de\/java\/java-12-features\/#Shenandoah_A_Low-Pause-Time_Garbage_Collector_Experimental\">seit Java 12 als Preview<\/a> im JDK enthalten. Mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/379\" target=\"_blank\">JDK Enhancement Proposal 379<\/a> wurde  Shenandoah f\u00fcr den produktiven Einsatz freigegeben.)<\/em><\/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-string-und-charsequence-methoden\">Neue String- und CharSequence-Methoden<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Die Klassen <code>String<\/code> und <code>CharSequence<\/code> wurden in Java 15 um einige Methoden erweitert. Diese Erweiterungen sind nicht in JDK Enhancement Proposals definiert.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"string-formatted\">String.formatted()<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Platzhalter in einem String konnten wir bisher beispielsweise wie folgt ersetzen:<\/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\">String message =\n    String.format(\n        <span class=\"hljs-string\">\"User %,d with username %s logged in at %s.\"<\/span>,\n        userId, username, ZonedDateTime.now());<\/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\">Ab Java 15 k\u00f6nnen wir eine alternative Syntax verwenden:<\/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\">String message =\n    <span class=\"hljs-string\">\"User %,d with username %s logged in at %s.\"<\/span>\n        .formatted(userId, username, ZonedDateTime.now());<\/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\">Welche Methode du verwendest, macht keinen Unterschied. Beide Methoden rufen letztendlich den folgenden Code auf:<\/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\">String message =\n    <span class=\"hljs-keyword\">new<\/span> Formatter()\n        .format(\n            <span class=\"hljs-string\">\"User %,d with username %s logged in at %s.\"<\/span>,\n            userId, username, ZonedDateTime.now())\n        .toString();<\/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\">Die Auswahl ist also letztlich Geschmacksache. Ich pers\u00f6nlich habe mich schnell mit der neuen Schreibweise angefreundet.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"string-stripindent\">String.stripIndent()<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Nehmen wir an, wir haben einen String, der in jeder Zeile einger\u00fcckt ist und der in jeder Zeile einige abschlie\u00dfende Leerzeichen hat, wie z. B. der folgende. Wir geben ihn \u2013 von zwei senkrechten Strichen begrenzt \u2013 zeilenweise aus. <\/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\">String html = <span class=\"hljs-string\">\"\"<\/span><span class=\"hljs-string\">\"\n      &lt;html&gt;    \\s\n        &lt;body&gt;      \\s\n          &lt;h1&gt;Hello!&lt;\/h1&gt;\n        &lt;\/body&gt;    \\s\n      &lt;\/html&gt;         \\s\\\n    \"<\/span><span class=\"hljs-string\">\"\"<\/span>;\n\nhtml.lines()\n    .map(line -&gt; <span class=\"hljs-string\">\"|\"<\/span> + line + <span class=\"hljs-string\">\"|\"<\/span>)\n    .forEachOrdered(System.out::println);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Wie du im ersten Kapitel gelernt hast, orientiert sich die Ausrichtung eines Textblocks in diesem Fall an den schlie\u00dfenden Anf\u00fchrungszeichen. Die Ausgabe sieht also so aus:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">|  &lt;html&gt;     |\n|    &lt;body&gt;       |\n|      &lt;h1&gt;Hello!&lt;\/h1&gt;|\n|    &lt;\/body&gt;     |\n|  &lt;\/html&gt;          |<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><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\">Mit der Methode <code>stripIndent()<\/code> k\u00f6nnen wir die Einr\u00fcckung und die abschlie\u00dfenden Leerzeichen entfernen:<\/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\">html.stripIndent()\n    .lines()\n    .map(line -&gt; <span class=\"hljs-string\">\"|\"<\/span> + line + <span class=\"hljs-string\">\"|\"<\/span>)\n    .forEachOrdered(System.out::println);<\/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\">Die Ausgabe ist nun:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">|&lt;html&gt;|\n|  &lt;body&gt;|\n|    &lt;h1&gt;Hello!&lt;\/h1&gt;|\n|  &lt;\/body&gt;|\n|&lt;\/html&gt;|<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><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=\"string-translateescapes\">String.translateEscapes()<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Gelegentlich bekommen wir es mit einem String zu tun, der escapete Escape-Sequenzen enth\u00e4lt, wie z. B. der folgende:<\/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\">String s = <span class=\"hljs-string\">\"foo\\\\nbar\\\\tbuzz\\\\\\\\\"<\/span>;\n\nSystem.out.println(s);<\/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<p class=\"wp-block-paragraph\">Die Ausgabe sieht wie folgt aus:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">foo\\nbar\\tbuzz\\\\<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><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\">Manchmal wollen wir aber die <em>ausgewerteten<\/em> Escape-Sequenzen darstellen, also einen Zeilenumbruch statt \"\\n\", einen Tab statt \"\\t\" und einen Backslash statt \"\\\\\".<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bisher mussten wir daf\u00fcr auf Third-Party-Libraries wie z. B. <a rel=\"noopener\" href=\"https:\/\/commons.apache.org\/proper\/commons-text\/\" target=\"_blank\">Apache Commons Text<\/a> zur\u00fcckgreifen:<\/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\">System.out.println(StringEscapeUtils.unescapeJava(s));<\/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\">Ab Java 15 k\u00f6nnen wir uns die zus\u00e4tzliche Abh\u00e4ngigkeit sparen und die JDK-Methode <code>String.translateEscapes()<\/code> einsetzen:<\/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\">System.out.println(s.translateEscapes());<\/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\">Die Ausgabe lautet nun:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">foo\nbar     buzz\\<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><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=\"charsequence-isempty\">CharSequence.isEmpty()<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Neu ist auch die Default-Methode <code>isEmpty()<\/code> im Interface <code>CharSequence<\/code>. Die Methode pr\u00fcft einfach, ob die L\u00e4nge der Zeichenfolge 0 ist:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-keyword\">boolean<\/span> <span class=\"hljs-title\">isEmpty<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n  <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">this<\/span>.length() == <span class=\"hljs-number\">0<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Diese Methode ist damit automatisch in den Klassen <code>Segment<\/code>, <code>StringBuffer<\/code> und <code>StringBuilder<\/code> verf\u00fcgbar.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><code>String<\/code> und <code>CharBuffer<\/code>, die ebenfalls <code>CharSequence<\/code> implementieren, haben jeweils eine eigene, optimierte implementierung von <code>isEmpty()<\/code>. Bei <code>String<\/code> z. B. ist der Aufruf von <code>length()<\/code> unn\u00f6tig teuer, da f\u00fcr die Berechnung der L\u00e4nge eines Strings seit Java 9 (<a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/254\" target=\"_blank\">JEP 254 \"Compact Strings\"<\/a>) auch dessen Encoding ber\u00fccksichtigt werden muss.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"helpful-nullpointerexceptions\">Helpful NullPointerExceptions<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Die <a href=\"\/de\/java\/java-14-features\/#Helpful_NullPointerExceptions\">in Java 14 eingef\u00fchrten \"Helpful NullPointerExceptions\"<\/a> sind ab Java 15 standardm\u00e4\u00dfig aktiviert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\"Helpful NullPointerExceptions\" zeigen uns nicht mehr nur, in <em>welcher Codezeile<\/em> eine <code>NullPointerException<\/code> aufgetreten ist, sondern auch <em>welche Variable<\/em> (oder welcher R\u00fcckgabewert) in der entsprechenden Zeile <code>null<\/code> ist und welche Methode deshalb nicht aufgerufen werden konnte.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ein Beispiel dazu findest du im oben verlinkten Artikel.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"performance-aenderungen\">Performance-\u00c4nderungen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Dieses Kapitel hie\u00df in den bisherigen Teilen der Serie \"Performance-<em>Verbesserungen<\/em>\". Die im ersten Abschnitt dieses Kapitels beschriebene \u00c4nderung kann allerdings zu einer sp\u00fcrbaren Leistungsverschlechterung f\u00fchren.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Daher habe ich mich entschieden, die \u00c4nderung in diesem Kapitel aufzunehmen und nicht unter \"Deprecations und L\u00f6schungen\" \u2013 und das Kapitel entsprechend umzubenennen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"disable-and-deprecate-biased-locking\">Disable and Deprecate Biased Locking<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Diese \u00c4nderung erkl\u00e4re ich am besten an einem Beispiel.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Der folgende <a rel=\"noopener\" href=\"https:\/\/github.com\/openjdk\/jmh\" target=\"_blank\">JMH<\/a>-Benchmark misst, wie lange es dauert einen <code>Vector<\/code> mit zehn Millionen Zahlen zu bef\u00fcllen (du findest den Code in diesem <a href=\"https:\/\/github.com\/SvenWoltmann\/biased-locking\" target=\"_blank\" rel=\"noopener\">GitHub-Repository<\/a>):<\/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-meta\">@Benchmark<\/span>\n<span class=\"hljs-meta\">@BenchmarkMode<\/span>(Mode.SampleTime)\n<span class=\"hljs-meta\">@Warmup<\/span>(iterations = <span class=\"hljs-number\">2<\/span>, time = <span class=\"hljs-number\">1<\/span>, timeUnit = TimeUnit.SECONDS)\n<span class=\"hljs-meta\">@Measurement<\/span>(iterations = <span class=\"hljs-number\">2<\/span>, time = <span class=\"hljs-number\">1<\/span>, timeUnit = TimeUnit.SECONDS)\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">void<\/span> <span class=\"hljs-title\">test<\/span><span class=\"hljs-params\">(Blackhole blackhole)<\/span> <\/span>{\n  Vector&lt;Integer&gt; vector = <span class=\"hljs-keyword\">new<\/span> Vector&lt;&gt;(<span class=\"hljs-number\">10_000_000<\/span>);\n  <span class=\"hljs-keyword\">for<\/span> (<span class=\"hljs-keyword\">int<\/span> i = <span class=\"hljs-number\">0<\/span>; i &lt; <span class=\"hljs-number\">10_000_000<\/span>; i++) {\n    vector.add(i);\n  }\n  blackhole.consume(vector);\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\">Ich empfehle den Test mit der VM-Option <code>-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC<\/code> zu starten, um den Epsilon Garbage Collector einzusetzen, der <a href=\"\/de\/java\/java-11-features\/#Epsilon_A_No-Op_Garbage_Collector\">seit Java 11<\/a> als experimenteller Garbage Collector Teil des JDK ist.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Der Epsilon GC f\u00fchrt keine Garbage Collection durch und ist damit sehr gut geeignet, um GC-Beeinflussungen bei Tests zu vermeiden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ich habe den Test auf meinem Dell XPS 15 mit einem Intel Core i7-10750H ausgef\u00fchrt \u2013 zun\u00e4chst mit Java 14. Du findest das vollst\u00e4ndige Testergebnis in der Datei <a rel=\"noopener\" href=\"https:\/\/github.com\/SvenWoltmann\/biased-locking\/blob\/main\/results\/vector_results_java14.txt\" target=\"_blank\">vector_results_java14.txt<\/a>. Die relevanten zwei Zeilen des Ergebnisses sind die folgenden:<\/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\">Benchmark                                         Mode  Cnt  Score   Error  Units\nBiasedLockingVectorBenchmark.test               sample  148  0,071 \u00b1 0,001   s\/op<\/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\">Unter Java 14 dauert es also im Mittel 71 Millisekunden, um einen <code>Vector<\/code> mit zehn Millionen Elementen zu bef\u00fcllen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Als n\u00e4chstes habe ich den Test mit Java 15 ausgef\u00fchrt. Das Testergebnis liegt in der Datei <a rel=\"noopener\" href=\"https:\/\/github.com\/SvenWoltmann\/biased-locking\/blob\/main\/results\/vector_results_java15.txt\" target=\"_blank\">vector_results_java15.txt<\/a>. Hier die relevanten Zeilen der Ausgabe:<\/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\">Benchmark                                         Mode  Cnt  Score   Error  Units\nBiasedLockingVectorBenchmark.test               sample   55  0,202 \u00b1 0,004   s\/op<\/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\">Unter Java 15 ben\u00f6tigt die gleiche Operation 202 Millisekunden, also <strong>fast dreimal so lang<\/strong>!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wie kommt es dazu?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Der Grund ist \u2013 wie die \u00dcberschrift des Abschnitts bereits verraten hat \u2013 die Deaktivierung von \"Biased Locking\".<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Was ist Biased Locking?<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Bei Biased Locking handelt es sich um eine Optimierung der Thread-Synchronisierung mit dem Ziel den Synchronisations-Overhead zu reduzieren, wenn derselbe Monitor immer wieder von demselben Thread erworben wird (d. h. wenn derselbe Thread immer wieder Code aufruft, der auf dem gleichen Objekt synchronisiert ist).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Im Beispiel oben bedeutet das, dass der <code>vector<\/code>-Monitor beim ersten Aufruf der <code>add()<\/code>-Methode auf den Thread ausgerichtet (\"gebiased\") wird, in dem die Test-Methode ausgef\u00fchrt wird. Dadurch wird der Erwerb des Monitors in den folgenden 9.999.999 Aufrufen der <code>add()<\/code>-Methode beschleunigt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die genaue Funktionsweise ist kompliziert, wobei wir bei der n\u00e4chsten Frage w\u00e4ren:<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Warum wurde Biased Locking deaktiviert? <\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Von Biased Locking profitieren haupts\u00e4chlich alte Anwendungen, die Datenstrukturen wie <code>Vector<\/code>, <code>Hashtable<\/code> oder <code>StringBuffer<\/code> verwenden, bei denen jeder Zugriff synchronisiert ist.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Moderne Anwendungen verwenden in der Regel nicht-synchronisierte Datenstrukturen wie <code>ArrayList<\/code>, <code>HashMap<\/code> oder <code>StringBuilder<\/code> \u2013 und die f\u00fcr Multithreading optimierten Datenstrukturen im Paket <code>java.util.concurrent<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Da der Code f\u00fcr Biased Locking extrem komplex ist und tief in den JVM-Code eingreift, erfordert er einen hohen Wartungsaufwand und macht \u00c4nderungen innerhalb des Synchronisationssystems der JVM aufw\u00e4ndig und fehleranf\u00e4llig.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Daher wurde im <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/374\" target=\"_blank\">JDK Enhancement Proposal 374<\/a> entschieden Biased Locking in Java 15 standardm\u00e4\u00dfig zu deaktivieren, als \"deprecated\" zu markieren und in einem der folgenden Releases vollst\u00e4ndig zu entfernen.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Was bedeutet das f\u00fcr uns Java-Entwicklerinnen und -Entwickler?<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Wenn nicht l\u00e4ngst geschehen, ist es sp\u00e4testens jetzt an der Zeit, <code>Vector<\/code> und <code>Hashtable<\/code> durch <code>ArrayList<\/code> und <code>HashMap<\/code> (oder andere geeignete Datenstrukturen) zu ersetzen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Der Vollst\u00e4ndigkeit halber hier noch ein Test f\u00fcr <code>ArrayList<\/code> (das vollst\u00e4ndige Ergebnis findest du in der Datei <a href=\"https:\/\/github.com\/SvenWoltmann\/biased-locking\/blob\/main\/results\/arraylist_results.txt\" target=\"_blank\" rel=\"noopener\">arraylist_results.txt<\/a>):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">Benchmark                               Mode  Cnt  Score   Error  Units\nArrayListBenchmark.test               sample  160  0,064 \u00b1 0,001   s\/op<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><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\"><code>ArrayList<\/code> ist also etwa 10 % schneller als <code>Vector<\/code> mit Biased Locking und mehr als dreimal so schnell wie <code>Vector<\/code> ohne Biased Locking.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"spezialisierte-implementierungen-von-treemap-methoden\">Spezialisierte Implementierungen von TreeMap-Methoden<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In <code>TreeMap<\/code> wurden spezialisierte Methoden <code>putIfAbsent()<\/code>, <code>computeIfAbsent()<\/code>, <code>computeIfPresent()<\/code>, <code>compute()<\/code> und <code>merge()<\/code> implementiert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Diese Methoden waren seit Java 8 ausschlie\u00dflich als Default-Methoden im <code>Map<\/code>-Interface spezifiziert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die <code>TreeMap<\/code>-spezifischen Implementierungen sind f\u00fcr den zugrunde liegenden <a href=\"\/de\/algorithmen\/rot-schwarz-baum-java\/\">Rot-Schwarz-Baum<\/a> optimiert; sie sind dementsprechend performanter als die Default-Methoden des Interfaces.   <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>(Die Erweiterung der TreeMap ist nicht in einem JDK Enhancement Proposal definiert.)<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"experimentelle-preview-und-incubator-features\">Experimentelle, Preview- und Incubator-Features<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In Java 15 gibt es mit \"Sealed Classes\" ein neues Preview-Feature. Drei weitere Features wurden in die zweite Preview- bzw. Incubator-Runde geschicht.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ich werde die neuen Features an dieser Stelle nicht in allen Details vorstellen, sondern auf das jeweilige Java-Release verweisen, in dem die Features Produktionsreife erreichen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"sealed-classes-preview\">Sealed Classes (Preview)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Es gibt verschiedene Gr\u00fcnde die Vererbbarkeit einer Klasse einzuschr\u00e4nken (welche das sind, erf\u00e4hrst du im <a href=\"\/de\/java\/sealed-classes\/#Warum_die_Erweiterbarkeit_einer_Klassenhierarchie_einschranken\">Hauptartikel \u00fcber Sealed Classes<\/a>).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bisher gab es jedoch nur begrenzte M\u00f6glichkeiten die Vererbbarkeit einer Klasse einzuschr\u00e4nken:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Die Klasse kann als <code>final<\/code> deklariert werden, so dass <em>generell<\/em> keine Unterklassen implementiert werden k\u00f6nnen.<\/li>\n\n\n\n<li>Die Klasse kann als package-private markiert werden und so nur Unterklassen <em>innerhalb des Pakets<\/em> erlauben. Dadurch ist die Oberklasse allerdings nicht mehr au\u00dferhalb des Pakets sichtbar, selbst wenn die abgeleiteten Klassen <code>public<\/code> gemacht werden. Das ist in den meisten F\u00e4llen unerw\u00fcnscht.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Die durch <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/360\" target=\"_blank\">JDK Enhancement Proposal 360<\/a> als Preview-Feature eingef\u00fchrten \"Sealed Classes\" bieten Entwicklerinnen und Entwicklern einer Java-Klasse oder eines Interfaces die M\u00f6glichkeit einzuschr\u00e4nken, welche anderen Klassen und Interfaces sie erweitern bzw. implementieren d\u00fcrfen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Eine versiegelte Klassenstruktur wird wie folgt definiert:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Das Keyword <code>sealed<\/code> markiert eine versiegelte Klasse.<\/li>\n\n\n\n<li>Mit dem Keyword <code>permits<\/code> werden die erlaubten Unterklassen aufgelistet.<\/li>\n\n\n\n<li>Eine Unterklasse einer versiegelten Klasse muss entweder <code>sealed<\/code>, <code>final<\/code> oder <code>non-sealed<\/code> sein. Im ersten Fall m\u00fcssen wiederum mit <code>permits<\/code> die erlaubten Unterklassen definiert werden. Der letzte Fall bedeutet, dass die Unterklasse wieder offen f\u00fcr Vererbung ist \u2013 genau wie eine regul\u00e4re Klasse. <\/li>\n<\/ul>\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-21\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-keyword\">public<\/span> sealed <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Shape<\/span> <span class=\"hljs-title\">permits<\/span> <span class=\"hljs-title\">Circle<\/span>, <span class=\"hljs-title\">Square<\/span>, <span class=\"hljs-title\">Rectangle<\/span>, <span class=\"hljs-title\">WeirdShape<\/span> <\/span>{ ... }\n\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Circle<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Shape<\/span> <\/span>{ ... }\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">final<\/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\">Shape<\/span> <\/span>{ ... }\n\n<span class=\"hljs-keyword\">public<\/span> sealed <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Rectangle<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Shape<\/span> \n    <span class=\"hljs-title\">permits<\/span> <span class=\"hljs-title\">TransparentRectangle<\/span>, <span class=\"hljs-title\">FilledRectangle<\/span> <\/span>{ ... }\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">TransparentRectangle<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Rectangle<\/span> <\/span>{ ... }\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-keyword\">final<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">FilledRectangle<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Rectangle<\/span> <\/span>{ ... }\n\n<span class=\"hljs-keyword\">public<\/span> non-sealed <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">WeirdShape<\/span> <span class=\"hljs-keyword\">extends<\/span> <span class=\"hljs-title\">Shape<\/span> <\/span>{ ... }<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Das folgende Klassendiagramm zeigt die im Beispielcode implementierte Klassenhierarchie. Die orangenen Rechtecke demonstrieren, dass die Hierarchie nur unter <code>WeirdShape<\/code> erweiterbar ist.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full_800\"><img decoding=\"async\" width=\"800\" height=\"312\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/sealed-classes-class-diagram-800x312.png\" alt=\"Klassenhierarchie mit &quot;Sealed Classes&quot;\" class=\"wp-image-24671\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/sealed-classes-class-diagram-800x312.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/sealed-classes-class-diagram-224x87.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/sealed-classes-class-diagram-336x131.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/sealed-classes-class-diagram-504x197.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/sealed-classes-class-diagram-672x262.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/sealed-classes-class-diagram-400x156.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/sealed-classes-class-diagram-600x234.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/sealed-classes-class-diagram-944x368.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/sealed-classes-class-diagram-1200x468.png 1200w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/sealed-classes-class-diagram.png 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><figcaption class=\"wp-element-caption\">Klassenhierarchie mit \"Sealed Classes\"<\/figcaption><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">In Kombination mit \"Pattern Matching for switch\", was in <a href=\"\/de\/java\/java-17-features\/#Pattern_Matching_for_switch_Preview\">Java 17<\/a> als Preview-Feature vorgestellt wird, werden versiegelte Klassen zudem eine Ersch\u00f6pfungsanalyse erm\u00f6glichen (d. h. der Compiler kann pr\u00fcfen, ob ein Switch-Ausdruck alle m\u00f6glichen Klassen abdeckt). Mehr dazu im <a href=\"\/de\/java\/sealed-classes\/#Vollstandigkeitsanalyse_bei_Pattern_Matching_for_switch\">Hauptartikel \u00fcber Sealed Classes<\/a>.   <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Um Sealed Classes bereits in Java 15 einzusetzen, musst du sie entweder in deiner IDE aktivieren (in IntelliJ \u00fcber <em>File\u2192Project Structure\u2192Project Settings\u2192Project\u2192Project language level<\/em>) oder mit der Option <code>--enable-preview<\/code> beim Aufruf der <code>javac<\/code>- und <code>java<\/code>-Kommandos.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"pattern-matching-for-instanceof-second-preview\">Pattern Matching for instanceof (Second Preview)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">\"Pattern Matching for instanceof\" wurde als <a href=\"\/de\/java\/java-14-features\/#Pattern_Matching_for_instanceof_Preview\">Preview in Java 14<\/a> vorgestellt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Mit dem <a href=\"https:\/\/openjdk.org:443\/jeps\/375\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 375<\/a> wird das Feature ohne \u00c4nderungen ein zweites Mal als Preview-Feature geliefert, um weiteres Feedback aus der Java-Community einzusammeln.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\"Pattern Matching for instanceof\" wird im kommenden Release, <a href=\"\/de\/java\/java-16-features\/#Pattern_Matching_for_instanceof\">Java 16<\/a>, produktionsreif sein.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"records-second-preview\">Records (Second Preview)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Records wurden ebenfalls als <a href=\"\/de\/java\/java-14-features\/#Records_Preview\">Preview-Feature in Java 14<\/a> pr\u00e4sentiert.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Eine schnelle Wiederholung: Mit einem Record definieren wir eine Klasse mit nur finalen Feldern, wie in folgendem Beispiel:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-22\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\"><span class=\"hljs-function\">record <span class=\"hljs-title\">Point<\/span><span class=\"hljs-params\">(<span class=\"hljs-keyword\">int<\/span> x, <span class=\"hljs-keyword\">int<\/span> y)<\/span> <\/span>{}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Wir k\u00f6nnen einen Record wie folgt instanziieren und dessen Felder auslesen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-23\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">Point p = <span class=\"hljs-keyword\">new<\/span> Point(<span class=\"hljs-number\">3<\/span>, <span class=\"hljs-number\">5<\/span>);\n<span class=\"hljs-keyword\">int<\/span> x = p.x();\n<span class=\"hljs-keyword\">int<\/span> y = p.y();<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/384\" target=\"_blank\">JDK Enhancement Proposal 384<\/a> wurde f\u00fcr Java 15 noch etwas Feinschliff vorgenommen:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Felder eines Records k\u00f6nnen nicht mehr per Reflection ver\u00e4ndert werden.<\/li>\n\n\n\n<li>Records k\u00f6nnen mit \"Sealed Interfaces\" kombiniert werden.<\/li>\n\n\n\n<li>Innerhalb von Methoden k\u00f6nnen \"lokale Records\" definiert werden.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">Gehen wir die \u00c4nderungen im Einzelnen durch...<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Felder eines Records per Reflection \u00e4ndern<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">In Java 14 war es noch m\u00f6glich, die eigentlich finalen Felder eines Records per Reflection zu \u00e4ndern. Das folgende Beispiel zeigt, wie man den <code>x<\/code>-Wert des oben gezeigten <code>Point<\/code>-Records <code>p<\/code> nachtr\u00e4glich \u00e4ndern konnte:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-24\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">Field X = Point<span class=\"hljs-class\">.<span class=\"hljs-keyword\">class<\/span>.<span class=\"hljs-title\">getDeclaredField<\/span>(\"<span class=\"hljs-title\">x<\/span>\")<\/span>;\nX.setAccessible(<span class=\"hljs-keyword\">true<\/span>);\nX.set(p, newX);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-24\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">In Java 15 f\u00fchrt dieser Versuch zu einer <code>IllegalAccessException<\/code>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Records und Sealed Interfaces<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Records k\u00f6nnen die ebenfalls als Preview-Feature in Java 15 hinzugekommenen \"Sealed Interfaces\" implementieren. Entsprechend d\u00fcrfen \"Sealed Interfaces\" auch Records in ihrer \"permits\"-Liste aufz\u00e4hlen.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Lokale Records<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Records d\u00fcrfen jetzt auch innerhalb von Methoden definiert werden und sind dann nur innerhalb dieser Methode sichtbar. Dies ist insbesondere n\u00fctzlich, wenn man Zwischenergebnisse mit mehreren zusammengeh\u00f6rigen Variablen speichern m\u00f6chte.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ein Beispiel daf\u00fcr findest du im <a href=\"\/de\/java\/java-records\/#Lokale_Records\">Hauptartikel \u00fcber Records<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>(Records werden im n\u00e4chsten Release, <a href=\"\/de\/java\/java-16-features\/#Records\">Java 16<\/a>, als finale Version ver\u00f6ffentlicht werden. Eine Vorstellung in allen Einzelheiten findest du im oben verlinkten Artikel.)<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"foreign-memory-access-api-second-incubator\">Foreign-Memory Access API (Second Incubator)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Das ebenfalls <a href=\"\/de\/java\/java-14-features\/#Foreign-Memory_Access_API_Incubator\">in Java 14 als Incubator vorgestellte<\/a> Foreign-Memory Access API erlaubt es Java-Anwendungen, effizient und sicher auf Speicher au\u00dferhalb des Java-Heaps zuzugreifen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/383\" target=\"_blank\">JDK Enhancement Proposal 383<\/a> wurden einige \u00c4nderungen am API vorgenommen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Diese Schnittstelle wird bis Java 18 im Incubator-Status bleiben und in <a href=\"\/de\/java\/java-19-features\/#Foreign_Function_Memory_API_Preview\">Java 19<\/a> als Foreign Function &amp; Memory API zum ersten Mal als Preview-Version erscheinen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"deprecations-und-loeschungen\">Deprecations und L\u00f6schungen<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In diesem Abschnitt findest du Features, die in Java 15 als \"deprecated\" markiert oder vollst\u00e4ndig aus dem JDK entfernt wurden.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"remove-the-nashorn-javascript-engine\">Remove the Nashorn JavaScript Engine<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Die im JDK 8 eingef\u00fchrte und <a href=\"\/de\/java\/java-11-features\/#Deprecate_the_Nashorn_JavaScript_Engine\">in Java 11 als \"deprecated\" markierte<\/a> JavaScript-Engine \"Nashorn\" wird durch das <a href=\"https:\/\/openjdk.org:443\/jeps\/372\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 372<\/a> in Java 15 vollst\u00e4ndig aus dem JDK entfernt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Als Grund geben die JDK-Entwickler die rasante Entwicklungsgeschwindigkeit von ECMAScript (dem Standard hinter JavaScript) an. Diese macht die Weiterentwicklung von Nashorn zu einer nicht zu bew\u00e4ltigenden Herausforderung.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"remove-the-solaris-and-sparc-ports\">Remove the Solaris and SPARC Ports<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Die Ports f\u00fcr das nicht ganz mehr zeitgem\u00e4\u00dfe Betriebssystem Solaris und die SPARC-Prozessorarchitektur wurden <a href=\"\/de\/java\/java-14-features\/#Deprecate_the_Solaris_and_SPARC_Ports\">in Java 14 als \"deprecated\" markiert<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/381\" target=\"_blank\">JDK Enhancement Proposal 381<\/a> werden die Portierungen Solaris\/SPARC, Solaris\/x64 und Linux\/SPARC in Java 15 endg\u00fcltig aus dem JDK entfernt, um die Entwicklungsresourcen f\u00fcr andere Projekte freizumachen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"deprecate-rmi-activation-for-removal\">Deprecate RMI Activation for Removal<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Java Remote Method Invocation (Java RMI) ist eine Technologie, die Objekten einer JVM den Aufruf von Methoden auf Objekten einer anderen JVM (\"entfernten Objekten\") erm\u00f6glicht.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ein faktisch nicht genutztes, aber aufw\u00e4ndig zu wartendes Feature von RMI ist RMI Activation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Durch RMI Activation kann ein Objekt, das auf der Ziel-JVM zerst\u00f6rt wurde, bei einem RMI-Aufruf automatisch neu instanziiert werden. Dadurch soll eine komplexe Fehlerbehandlung im RMI-Client vermieden werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Es zeigt sich jedoch, dass die tats\u00e4chliche Nutzung von RMI Activation verschwindend gering ist. Die JDK-Entwickler haben dazu Open-Source-Projekte, Stack Overflow und andere Foren nach RMI Activation durchsucht und nahezu keine Erw\u00e4hnung gefunden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die durch RMI Activation verursachten fortlaufenden Wartungskosten stehen somit in keinem Verh\u00e4ltnis zum Nutzen. RMI Activation wird daher durch <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/385\" target=\"_blank\">JEP 385<\/a> als \"deprecated for removal\" markiert. Im \u00fcbern\u00e4chsten Release, <a href=\"\/de\/java\/java-17-features\/#Remove_RMI_Activation\">Java 17<\/a>, wird es komplett entfernt werden.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"sonstige-aenderungen-in-java-15\">Sonstige \u00c4nderungen in Java 15<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In diesem Kapitel haben ich \u00c4nderungen aufgelistet, die man als Java-Entwicklerin oder -Entwickler nicht zwingend kennen muss. Es schadet aber auch nicht, diesen Abschnitt einmal zu \u00fcberfliegen :-)  <\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"hidden-classes\">Hidden Classes<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Application Frameworks wie Java EE und Spring generieren zahlreiche Klassen dynamisch zur Laufzeit. Insbesondere erstellen sie Proxys f\u00fcr Anwendungsklassen, um Funktionen wie Zugriffskontrolle, Caching, Transaktionsmanagment und JPA Lazy Loading hinzuzuf\u00fcgen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Die vorhandenen APIs <code>ClassLoader.defineClass()<\/code> und <code>Lookup.defineClass()<\/code> generieren Bytecode, der nicht von dem Bytecode zu unterscheiden ist, der beim Compilieren von statischen Anwendungsklassen entsteht.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Somit sind die dynamisch erzeugten Klassen f\u00fcr alle anderen Klassen der Class-Loader-Hierarchie auffindbar und existieren so lange wie der Class Loader, in dem sie generiert wurden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Dies ist in der Regel unerw\u00fcnscht. Zum einen gelten sie meist als Framework-spezifische Implementierungsdetails, die vor dem Rest der Anwendung verborgen bleiben sollen; zum anderen werden sie oft nur f\u00fcr eine bestimmte Zeit ben\u00f6tigt, so dass sie nach ihrer Nutzung den Speicherbedarf der Anwendung unn\u00f6tig erh\u00f6hen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Durch das <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/371\" target=\"_blank\">JDK Enhancement Proposal 371<\/a> haben in Java 15 \"Hidden Classes\" Einzug ins JDK gehalten.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Hidden Classes werden \u00fcber die Methode <code>MethodHandles.Lookup.defineHiddenClass()<\/code> definiert und k\u00f6nnen von anderen Klassen nicht verwendet werden \u2013 weder direkt, noch \u00fcber Reflection.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Da das Feature von den meisten Java-Entwicklerinnen und -Entwicklern nicht direkt eingesetzt werden wird, verzichte ich hier auf tiefergehende Details.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"edwards-curve-digital-signature-algorithm-eddsa\">Edwards-Curve Digital Signature Algorithm (EdDSA)<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">EdDSA ist ein modernes Signaturverfahren, das bei gleicher Sicherheitsst\u00e4rke schneller ist als bisherige Signaturverfahren, wie DSA und ECDSA. EdDSA wird von vielen Kryptobibliotheken wie OpenSSL und BoringSSL unterst\u00fctzt. Viele Benutzer verwenden bereits EdDSA-Zertifikate.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Durch das <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/339\" target=\"_blank\">JDK Enhancement Proposal 339<\/a> erh\u00e4lt der EdDSA-Signaturalgorithmus Einzug in Java 15.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Das folgende Beispiel zeigt, wie du f\u00fcr die Nachricht \"Happy Coding!\" eine digitale Signatur erstellen kannst:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-25\" data-shcb-language-name=\"Java\" data-shcb-language-slug=\"java\"><span><code class=\"hljs language-java\">String message = <span class=\"hljs-string\">\"Happy Coding!\"<\/span>;\n\nKeyPairGenerator kpg = KeyPairGenerator.getInstance(<span class=\"hljs-string\">\"Ed25519\"<\/span>);\nKeyPair kp = kpg.generateKeyPair();\n\nSignature sig = Signature.getInstance(<span class=\"hljs-string\">\"Ed25519\"<\/span>);\nsig.initSign(kp.getPrivate());\nsig.update(message.getBytes(StandardCharsets.UTF_8));\n<span class=\"hljs-keyword\">byte<\/span>&#091;] signature = sig.sign();\n\nSystem.out.println(<span class=\"hljs-string\">\"signature = \"<\/span> + Base64.getEncoder().encodeToString(signature));<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-25\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Java<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">java<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"wp-block-paragraph\">Wenn du das Programm unter einem \u00e4lteren Release als Java 15 laufen l\u00e4sst, bekommst du eine <code>NoSuchAlgorithmException<\/code> mit der Nachricht \"Ed25519 KeyPairGenerator not available\".<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"reimplement-the-legacy-datagramsocket-api\">Reimplement the Legacy DatagramSocket API<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Die in <code>java.net.DatagramSocket<\/code> und <code>java.net.MulticastSocket<\/code> implementierte \"DatagramSocket API\" existiert seit Java 1.0 und ist eine Mischung aus veraltetem, schwer wart- und erweiterbarem Java- und C-Code.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Inbesondere die IPv6-Unterst\u00fctzung ist nicht sauber implementiert, und es existieren einige Concurrency Bugs, die sich ohne gr\u00f6\u00dfere Refactoring nicht beheben lassen. Auch l\u00e4sst sich der bestehenden Code nicht gut an <a href=\"\/de\/java\/virtual-threads\/\">Virtuelle Threads<\/a> (leichtgewichtige, von der JVM verwaltete Threads) anpassen, die aktuell in <a rel=\"noopener\" href=\"https:\/\/openjdk.org\/projects\/loom\/\" target=\"_blank\">Projekt Loom<\/a> entwickelt werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Durch den <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/373\" target=\"_blank\">JDK Enhancement Proposal 373<\/a> wird die API durch eine einfachere, modernere, leichter wartbare und an Virtuelle Threads anpassbare Implementierung ersetzt.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Bereits in <a href=\"\/de\/java\/java-13-features\/#Reimplement_the_Legacy_Socket_API\">Java 13<\/a> wurde die ebenfalls aus Java 1.0 stammende \"Socket API\" neu implementiert.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"keine-kopplung-von-compressed-oops-und-compressed-class-pointers\">Keine Kopplung von Compressed Oops und Compressed Class Pointers<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Bisher waren <a href=\"https:\/\/www.happycoders.eu\/de\/java\/object-headers-compressed-class-pointers\/#compressed-class-pointers\">Compressed Class Pointers<\/a>&nbsp;und <a href=\"https:\/\/www.happycoders.eu\/de\/java\/compressed-oops\/\">Compressed OOPs<\/a> gekoppelt: Wenn man Compressed OOPs deaktivierte, wurden automatisch auch Compressed Class Pointers deaktiviert. Da es keinen Grund f\u00fcr diese Einschr\u00e4nkung gab, wurde sie in&nbsp;Java 15&nbsp;aufgehoben.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>(F\u00fcr diese \u00c4nderung existiert kein JDK Enhancement Proposal, sie ist im Bug-Tracker unter <\/em><a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8241825\" target=\"_blank\" rel=\"noopener\">JDK-8241825<\/a><em> beschrieben.)<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"komprimierte-heap-dumps\">Komprimierte Heap Dumps<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Um die auf dem Heap liegenden Objekte einer laufenden Anwendung zu analyiseren, kann man wie folgt einen Heap-Dump erstellen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-26\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">jcmd &lt;Prozess-ID&gt; GC.heap_dump &lt;Dateiname&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-26\"><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=\"has-text-align-left wp-block-paragraph\">Je nach Art der Anwendung kann die generierte Datei mehrere GB gro\u00df werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Seit Java 15 gibt es die Option die Datei ZIP-komprimiert zu speichern. Dazu muss der Parameter <code>-gz<\/code> mit einem Wert von 1 (schnellste Kompression) bis 9 (beste Kompression) angegeben werden. Hier ein Beispiel:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-27\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">jcmd 10664 GC.heap_dump \/tmp\/heap.dmp -gz=5<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-27\"><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\">Basierend auf einigen Tests, w\u00fcrde ich in der Regel den Kompressionslevel 1 empfehlen. Dieser erreicht eine Reduktion des Dumps auf etwa 30 % seiner Originalgr\u00f6\u00dfe. Kompressionslevel 9 schafft 26 %, braucht daf\u00fcr aber mehr als 20 mal so lange.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>(F\u00fcr diese \u00c4nderung existiert kein JDK Enhancement Proposal, sie ist im Bug-Tracker unter <a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8237354\" target=\"_blank\" rel=\"noopener\">JDK-8237354<\/a> beschrieben.)<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"support-fuer-unicode-13-0\">Support f\u00fcr Unicode 13.0<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Eine Anhebung des Unicode-Supports begleitet uns in nahezu jedem Java-Release:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Java 11: Unicode 10<\/li>\n\n\n\n<li>Java 12: Unicode 11<\/li>\n\n\n\n<li>Java 13: Unicode 12.1<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">In Java 15 wird der Support nun auf Unicode 13.0 angehoben. Relevant ist das u. a. f\u00fcr die Klassen <code>String<\/code> und <code>Character<\/code>, die mit den neuen Zeichen, Codebl\u00f6cken und Schriftsystemen umgehen k\u00f6nnen m\u00fcssen.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Ein Beispiel findest du im <a href=\"\/de\/java\/java-11-features\/#Unicode_10\">Artikel \u00fcber Java 11<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><em>(F\u00fcr die Unterst\u00fctzung von Unicode 13.0 existiert kein JDK Enhancement Proposal; die \u00c4nderung ist im Bug-Tracker unter <a href=\"https:\/\/bugs.openjdk.org\/browse\/JDK-8239383\" target=\"_blank\" rel=\"noopener\">JDK-8239383<\/a> beschrieben.)<\/em><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"vollstaendige-liste-aller-aenderungen-in-java-15\">Vollst\u00e4ndige Liste aller \u00c4nderungen in Java 15<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Dieser Artikel hat alle Features von Java 15 vorgestellt, die in JDK Enhancement Proposals definiert sind, sowie einige Performance-Verbesserungen und L\u00f6schungen, die keinem JEP zugeordnet sind.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Eine vollst\u00e4ndige Liste aller \u00c4nderungen findest du in den <a href=\"https:\/\/www.oracle.com\/java\/technologies\/javase\/15-relnote-issues.html\" target=\"_blank\" rel=\"noopener\">offiziellen Java 15 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 15 war wieder ein beeindruckendes Release:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Mit Text Blocks k\u00f6nnen wir endlich mehrzeilige Strings leserlich darstellen.<\/li>\n\n\n\n<li>Die neuen Garbage Collectoren ZGC und Shenandoah k\u00f6nnen wir einsetzen, wenn wir die Pausezeiten unserer Applikation auf unter 10 ms reduzieren wollen.<\/li>\n\n\n\n<li><code>String<\/code> wurde um die Funktionen <code>formatted()<\/code>, <code>stripIndent()<\/code> und <code>translateEscapes()<\/code> erweitert.<\/li>\n\n\n\n<li>Helpful NullPointerExceptions sind seit Java 15 standardm\u00e4\u00dfig aktiviert.<\/li>\n\n\n\n<li>Durch die Deaktivierung von Biased Locking k\u00f6nnen Legacy-Anwendungen, die Datenstrukturen wie <code>Vector<\/code> oder <code>Hashtable<\/code> verwenden, sp\u00fcrbar langsamer werden.<\/li>\n\n\n\n<li>Die TreeMap-Methoden <code>putIfAbsent()<\/code>, <code>computeIfAbsent()<\/code>, <code>computeIfPresent()<\/code>, <code>compute()<\/code> und <code>merge()<\/code> sind daf\u00fcr schneller geworden.<\/li>\n\n\n\n<li><span style=\"color: initial;\">Mit \"Sealed Classes\" wurde ein weiteres Feature aus <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/projects\/amber\/\" target=\"_blank\">Project Amber<\/a> als Preview aufgenommen; f\u00fcr Records und \"Pattern Matching for instanceof\" gab es ein zweites Preview.<\/span><\/li>\n\n\n\n<li>Entfernt wurde unter anderem die JavaScript Engine \"Nashorn\".<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Wenn dir der Artikel gefallen hat, hinterlass mir gerne einen Kommentar oder teile den Artikel \u00fcber einen der Share-Buttons am Ende.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Wenn du informiert werden m\u00f6chtest, wenn der n\u00e4chste Teil der Serie ver\u00f6ffentlicht wirst, <a href=\"#\" data-formkit-toggle=\"d8ee997126\">klicke hier<\/a>, um dich f\u00fcr den kostenlosen HappyCoders-Newsletter anzumelden.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Alle neuen Features von Java 15 mit Beispielen: Text Blocks, ZGC + Shenandoah, neue String-Methoden, Biased Locking, Preview f\u00fcr Sealed Classes und mehr...<\/p>\n","protected":false},"author":1,"featured_media":34268,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_seopress_titles_title":"","_seopress_titles_desc":"Die neuen Features von Java 15 mit Beispielen: Text Blocks, ZGC + Shenandoah, neue String-Methoden, Preview f\u00fcr Sealed Classes und mehr...","_seopress_robots_index":"","_seopress_robots_follow":"","_seopress_robots_imageindex":"","_seopress_robots_snippet":"","_seopress_robots_primary_cat":"none","_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":"both","_seopress_redirections_param":"","_seopress_redirections_type":301,"_seopress_analysis_target_kw":"java 15,java 15 features","_seopress_news_disabled":"","_seopress_video_disabled":"","_seopress_video":[],"_seopress_pro_schemas_manual":[{"_seopress_pro_rich_snippets_type":"none"}],"_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":29319,"_post_count":0,"footnotes":""},"categories":[64],"tags":[176],"class_list":["post-24522","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\/2021\/11\/java-15-features.jpg",1770,986,false],"thumbnail":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-15-features.jpg",150,84,false],"medium":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-15-features.jpg",300,167,false],"medium_large":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-15-features.jpg",768,428,false],"large":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-15-features.jpg",1024,570,false],"feature_thumb_224":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-15-features-224x125.jpg",224,125,true],"feature_thumb_336":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-15-features-336x187.jpg",336,187,true],"feature_thumb_504":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-15-features-504x281.jpg",504,281,true],"feature_thumb_672":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-15-features-672x374.jpg",672,374,true],"half_400":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-15-features-400x223.jpg",400,223,true],"half_600":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-15-features-600x334.jpg",600,334,true],"full_800":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-15-features-800x446.jpg",800,446,true],"full_944":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-15-features-944x526.jpg",944,526,true],"full_1200":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-15-features-1200x668.jpg",1200,668,true],"wide_1180":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-15-features-1180x490.jpg",1180,490,true],"wide_1770":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-15-features-1770x735.jpg",1770,735,true],"1536x1536":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-15-features.jpg",1536,856,false],"2048x2048":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-15-features.jpg",1770,986,false]},"uagb_author_info":{"display_name":"Sven Woltmann","author_link":"https:\/\/www.happycoders.eu\/de\/author\/sven\/"},"uagb_comment_info":0,"uagb_excerpt":"Alle neuen Features von Java 15 mit Beispielen: Text Blocks, ZGC + Shenandoah, neue String-Methoden, Biased Locking, Preview f\u00fcr Sealed Classes und mehr...","public_identification_id":"3a17fb8b205347d4800fb2159da7049f","private_identification_id":"1d9c51f016d2451281f4d634fd1b5475","_links":{"self":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/24522","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=24522"}],"version-history":[{"count":12,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/24522\/revisions"}],"predecessor-version":[{"id":56055,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/24522\/revisions\/56055"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/media\/34268"}],"wp:attachment":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/media?parent=24522"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/categories?post=24522"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/tags?post=24522"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}