{"id":23825,"date":"2021-11-01T14:45:00","date_gmt":"2021-11-01T13:45:00","guid":{"rendered":"https:\/\/www.happycoders.eu\/?p=23825"},"modified":"2026-01-11T19:54:33","modified_gmt":"2026-01-11T18:54:33","slug":"java-12-features","status":"publish","type":"post","link":"https:\/\/www.happycoders.eu\/de\/java\/java-12-features\/","title":{"rendered":"Java 12 Features (mit Beispielen)"},"content":{"rendered":"\n<p>Java 12, ver\u00f6ffentlicht am 19. M\u00e4rz 2019, ist das erste \"Zwischen-Release\" nach dem letzten Long-Term-Support (LTS)-Release, Java 11.<\/p>\n\n\n\n<p>Die \u00c4nderungen an Java 12 fallen im Vergleich zu den vorherigen Versionen etwas \u00fcbersichtlicher aus. Zum ersten Mal seit Java 7 gibt es keine \u00c4nderung an der Sprache selbst.<\/p>\n\n\n\n<p>Ich habe die \u00c4nderungen nach Relevanz f\u00fcr die t\u00e4gliche Entwicklerarbeit sortiert. Am Beginn des Artikels stehen Erweiterungen der Klassenbibliothek. Es folgen Performance-Verbesserungen, experimentelle und Preview-Features und zuletzt kleinere \u00c4nderungen, mit denen du als Entwickler wahrscheinlich nicht konfrontiert wirst.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"neue-string-und-files-methoden\">Neue String- und Files-Methoden<\/h2>\n\n\n\n<p>Nachdem wir in <a href=\"\/de\/java\/java-11-features\/#Neue_String-Methoden\">Java 11 einige neue String-Methoden<\/a> und die Methoden <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-11-features\/#FilesreadString_und_writeString\">Files.readString() und writeString()<\/a> erhalten haben, haben die JDK-Entwickler beide Klassen f\u00fcr Java 12 nochmals erweitert.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"string-indent\">String.indent()<\/h3>\n\n\n\n<p>Um einen String einzur\u00fccken, mussten wir uns bisher immer eine kleine Hilfsmethode schreiben, die die gew\u00fcnschte Anzahl Leerzeichen vor den String setzte. Sollte das \u00fcber mehrere Zeilen funktionieren, wurde die Methode entsprechend komplex.<\/p>\n\n\n\n<p>Java 12 hat mit <code>String.indent()<\/code> eine solche Methode eingebaut. Das folgende Beispiel zeigt, wie ein mehrzeiliger String um 4 Zeichen einger\u00fcckt wird:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Kotlin\" data-shcb-language-slug=\"kotlin\"><span><code class=\"hljs language-kotlin\">String s = <span class=\"hljs-string\">\"I am\\na multiline\\nString.\"<\/span>;\nSystem.<span class=\"hljs-keyword\">out<\/span>.println(s);\nSystem.<span class=\"hljs-keyword\">out<\/span>.println(s.indent(<span class=\"hljs-number\">4<\/span>));<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">Kotlin<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">kotlin<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Das Programm gibt folgendes aus:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"Klartext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">I am\na multiline\nString.\n    I am\n    a multiline\n    String.<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><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-transform\">String.transform()<\/h3>\n\n\n\n<p>Die neue Methode <code>String.transform()<\/code> wendet eine beliebige Funktion auf einen String an und gibt den R\u00fcckgabewert der Funktion zur\u00fcck. Hier ein paar Beispiele:<\/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 uppercase = <span class=\"hljs-string\">\"abcde\"<\/span>.transform(String::toUpperCase);\nInteger i        = <span class=\"hljs-string\">\"12345\"<\/span>.transform(Integer::valueOf);\nBigDecimal big   = <span class=\"hljs-string\">\"1234567891011121314151617181920\"<\/span>.transform(BigDecimal::<span class=\"hljs-keyword\">new<\/span>);<\/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>Wenn du dir den Quellcode von <code>String.transform()<\/code> anschaust, wirst du feststellen, dass hier keine Raketenwissenschaft am Werk ist, sondern die \u00fcbergebene Methodenreferenz als <code>Function<\/code> interpretiert und der String an deren <code>apply()<\/code>-Methode \u00fcbergeben wird:<\/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\">public<\/span> &lt;R&gt; <span class=\"hljs-function\">R <span class=\"hljs-title\">transform<\/span><span class=\"hljs-params\">(Function&lt;? <span class=\"hljs-keyword\">super<\/span> String, ? extends R&gt; f)<\/span> <\/span>{\n  <span class=\"hljs-keyword\">return<\/span> f.apply(<span class=\"hljs-keyword\">this<\/span>);\n}<\/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>Warum sollte man dann <code>transform()<\/code> verwenden statt einfach folgendes zu schreiben?<\/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 uppercase = <span class=\"hljs-string\">\"abcde\"<\/span>.toUpperCase();\nInteger i        = Integer.valueOf(<span class=\"hljs-string\">\"12345\"<\/span>);\nBigDecimal big   = <span class=\"hljs-keyword\">new<\/span> BigDecimal(<span class=\"hljs-string\">\"1234567891011121314151617181920\"<\/span>);<\/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>Der Vorteil von <code>String.transform()<\/code> liegt darin, dass die anzuwendende Funktion dynamisch zur Laufzeit bestimmt werden kann, w\u00e4hrend bei der letzten Schreibweise die Konvertierung zur Compile-Zeit festgelegt wird.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"files-mismatch\">Files.mismatch()<\/h3>\n\n\n\n<p>Mit der Methode <code>Files.mismatch()<\/code> kann der Inhalt zweiter Dateien verglichen werden.<\/p>\n\n\n\n<p>Die Methode gibt -1 zur\u00fcck, wenn beide Dateien gleich sind. Ansonsten gibt sie die Position des ersten Bytes an, in dem sich beide Dateien unterscheiden. Wird das Ende einer Datei erreicht, bevor ein Unterschied festgestellt wurde, wird die L\u00e4nge dieser Datei zur\u00fcckgegeben.<\/p>\n\n\n\n<p><em>(Die neuen String- und Files-Methoden sind nicht in einem JDK Enhancement Proposal definiert.)<\/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=\"der-teeing-collector\">Der Teeing Collector<\/h2>\n\n\n\n<p>F\u00fcr manche Anforderungen m\u00f6chte man einen Stream nicht mit einem, sondern mit zwei Collectoren terminieren und das Ergebnis beider Collectoren kombinieren.<\/p>\n\n\n\n<p>In folgendem Beispiel-Quellcode m\u00f6chten wir aus einem Stream von Zufallszahlen die Differenz von gr\u00f6\u00dfter zu kleinster Zahl bestimmen (wir verwenden das <a rel=\"noopener\" href=\"\/de\/java\/java-10-features\/#OptionalorElseThrow\" target=\"_blank\">in Java 10 eingef\u00fchrte <code>Optional.orElseThrow()<\/code><\/a>, um eine Markierung als \"Code Smell\" zu vermeiden):<\/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\">Stream&lt;Integer&gt; numbers = <span class=\"hljs-keyword\">new<\/span> Random().ints(<span class=\"hljs-number\">100<\/span>).boxed();\n\n<span class=\"hljs-keyword\">int<\/span> min = numbers.collect(Collectors.minBy(Integer::compareTo)).orElseThrow();\n<span class=\"hljs-keyword\">int<\/span> max = numbers.collect(Collectors.maxBy(Integer::compareTo)).orElseThrow();\n<span class=\"hljs-keyword\">long<\/span> range = (<span class=\"hljs-keyword\">long<\/span>) max - min;<\/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>Das Programm compiliert zwar, bricht allerdings zur Laufzeit mit einer Exception ab:<\/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\">Exception in thread \"main\" java.lang.IllegalStateException: \n        stream has already been operated upon or closed\n    at java.base\/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:229)\n    at java.base\/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:578)\n    at eu.happycoders.sandbox.TeeingCollectorTest.main(TeeingCollectorTest.java:12)<\/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>Der Exception-Text l\u00e4sst uns unmissverst\u00e4ndlich wissen, dass wir einen Stream nur einmal terminieren d\u00fcrfen.<\/p>\n\n\n\n<p>Wie k\u00f6nnen wir die Aufgabe l\u00f6sen?<\/p>\n\n\n\n<p>Eine Variante w\u00e4re es einen eigenen Collector zu schreiben, der Minimum und Maximum in einem int-Array mit zwei Elementen akkumuliert:<\/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\">Stream&lt;Integer&gt; numbers = <span class=\"hljs-keyword\">new<\/span> Random().ints(<span class=\"hljs-number\">100<\/span>).boxed();\n\n<span class=\"hljs-keyword\">int<\/span>&#091;] result =\n    numbers.collect(\n        () -&gt; <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-keyword\">int<\/span>&#091;] {Integer.MAX_VALUE, Integer.MIN_VALUE},\n        (minMax, i) -&gt; {\n          <span class=\"hljs-keyword\">if<\/span> (i &lt; minMax&#091;<span class=\"hljs-number\">0<\/span>]) minMax&#091;<span class=\"hljs-number\">0<\/span>] = i;\n          <span class=\"hljs-keyword\">if<\/span> (i &gt; minMax&#091;<span class=\"hljs-number\">1<\/span>]) minMax&#091;<span class=\"hljs-number\">1<\/span>] = i;\n        },\n        (minMax1, minMax2) -&gt; {\n          <span class=\"hljs-keyword\">if<\/span> (minMax2&#091;<span class=\"hljs-number\">0<\/span>] &lt; minMax1&#091;<span class=\"hljs-number\">0<\/span>]) minMax1&#091;<span class=\"hljs-number\">0<\/span>] = minMax2&#091;<span class=\"hljs-number\">0<\/span>];\n          <span class=\"hljs-keyword\">if<\/span> (minMax2&#091;<span class=\"hljs-number\">1<\/span>] &gt; minMax1&#091;<span class=\"hljs-number\">1<\/span>]) minMax1&#091;<span class=\"hljs-number\">1<\/span>] = minMax2&#091;<span class=\"hljs-number\">1<\/span>];\n        });\n\n<span class=\"hljs-keyword\">long<\/span> range = (<span class=\"hljs-keyword\">long<\/span>) result&#091;<span class=\"hljs-number\">1<\/span>] - result&#091;<span class=\"hljs-number\">0<\/span>];<\/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>Das ist zum einen recht aufw\u00e4ndig, zum anderen nicht gut lesbar.<\/p>\n\n\n\n<p>Mit dem in Java 12 eingef\u00fchrten \"Teeing Collector\" geht es einfacher. Wir k\u00f6nnen zwei Collectoren angeben (sogenannte Downstream-Collectoren) und eine Merger-Funktion, die die Ergebnisse der beiden Collectoren kombiniert:<\/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\">Stream&lt;Integer&gt; numbers = <span class=\"hljs-keyword\">new<\/span> Random().ints(<span class=\"hljs-number\">100<\/span>).boxed();\n\n<span class=\"hljs-keyword\">long<\/span> range =\n    numbers.collect(\n        Collectors.teeing(\n            Collectors.minBy(Integer::compareTo),\n            Collectors.maxBy(Integer::compareTo),\n            (min, max) -&gt; (<span class=\"hljs-keyword\">long<\/span>) max.orElseThrow() - min.orElseThrow()));<\/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>Deutlich eleganter und lesbarer, oder?<\/p>\n\n\n\n<p>Zum Abschluss die Frage: Warum hei\u00dft dieser Collector eigentlich \"Teeing Collector\"?<\/p>\n\n\n\n<p>Der Name kommt von der englischen Aussprache des Buchstabens \"T\", da die grafische Darstellung des Collectors wie ein ... \"T\" aussieht:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-half_600\"><img decoding=\"async\" width=\"600\" height=\"488\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/teeing-collector-v2-600x488.png\" alt=\"Teeing Collector\" class=\"wp-image-23692\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/teeing-collector-v2-600x488.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/teeing-collector-v2-224x182.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/teeing-collector-v2-336x273.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/teeing-collector-v2-504x410.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/teeing-collector-v2-672x547.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/teeing-collector-v2-400x325.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/teeing-collector-v2-800x651.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/teeing-collector-v2-944x768.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/teeing-collector-v2.png 1200w\" sizes=\"(max-width: 600px) 100vw, 600px\" \/><\/figure>\n<\/div>\n\n\n<p><em>(Auch zum Teeing Collector gibt es kein JDK Enhancement Proposal.)<\/em> <\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"support-for-compact-number-formatting\">Support for Compact Number Formatting<\/h2>\n\n\n\n<p>Mit der statischen Methode <code>NumberFormat.getCompactNumberInstance()<\/code> k\u00f6nnen wir einen Formatierer f\u00fcr die sogenannte \"kompakte Zahlenformatierung\" erzeugen. Das ist eine f\u00fcr den Menschen leicht lesbare Form, wie z. B. \"2&nbsp;Mio.\" oder \"3 Milliarden\".<\/p>\n\n\n\n<p>Das folgende Beispiel zeigt, wie einige Zahlen einmal in der kurzen und einmal in der langen kompakten Form dargestellt werden:<\/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\">NumberFormat nfShort =\n    NumberFormat.getCompactNumberInstance(Locale.GERMAN, NumberFormat.Style.SHORT);\nNumberFormat nfLong =\n    NumberFormat.getCompactNumberInstance(Locale.GERMAN, NumberFormat.Style.LONG);\n\nSystem.out.println(<span class=\"hljs-string\">\"        1.000 short -&gt; \"<\/span> + nfShort.format(<span class=\"hljs-number\">1_000<\/span>));\nSystem.out.println(<span class=\"hljs-string\">\"      456.789 short -&gt; \"<\/span> + nfShort.format(<span class=\"hljs-number\">456_789<\/span>));\nSystem.out.println(<span class=\"hljs-string\">\"    2.000.000 short -&gt; \"<\/span> + nfShort.format(<span class=\"hljs-number\">2_000_000<\/span>));\nSystem.out.println(<span class=\"hljs-string\">\"3.456.789.000 short -&gt; \"<\/span> + nfShort.format(<span class=\"hljs-number\">3_456_789_000L<\/span>));\nSystem.out.println();\nSystem.out.println(<span class=\"hljs-string\">\"        1.000 long -&gt; \"<\/span> + nfLong.format(<span class=\"hljs-number\">1_000<\/span>));\nSystem.out.println(<span class=\"hljs-string\">\"      456.789 long -&gt; \"<\/span> + nfLong.format(<span class=\"hljs-number\">456_789<\/span>));\nSystem.out.println(<span class=\"hljs-string\">\"    2.000.000 long -&gt; \"<\/span> + nfLong.format(<span class=\"hljs-number\">2_000_000<\/span>));\nSystem.out.println(<span class=\"hljs-string\">\"3.456.789.000 long -&gt; \"<\/span> + nfLong.format(<span class=\"hljs-number\">3_456_789_000L<\/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<p>Das Programm gibt folgendes 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\">        1.000 short -&gt; 1.000\n      456.789 short -&gt; 456.789\n    2.000.000 short -&gt; 2\u00a0Mio.\n3.456.789.000 short -&gt; 3\u00a0Mrd.\n\n        1.000 long -&gt; 1 Tausend\n      456.789 long -&gt; 457 Tausend\n    2.000.000 long -&gt; 2 Millionen\n3.456.789.000 long -&gt; 3 Milliarden<\/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>\"Compact Number Formats\" ist im gleichnamigen <a rel=\"noopener\" href=\"https:\/\/unicode.org\/reports\/tr35\/tr35-numbers.html#Compact_Number_Formats\" target=\"_blank\">Unicode-Standard<\/a> definiert.<\/p>\n\n\n\n<p><em>(Ein JDK Enhancement Proposal existiert nicht f\u00fcr \"Compact Number Formatting\".)<\/em><\/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>Die folgenden Verbesserungen sorgen daf\u00fcr, dass unsere Java-Applikationen schneller starten, niedrigere Garbage-Collector-Latenzen und einen besseren Memory-Footprint haben.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"default-cds-archives\">Default CDS Archives<\/h3>\n\n\n\n<p>Im Artikel \u00fcber Java 10 findest du eine Beschreibung von <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-10-features\/#Class-Data_Sharing\">Class-Data Sharing (CDS)<\/a>.<\/p>\n\n\n\n<p>Um Class-Data Sharing zu aktivieren, musstest du bisher f\u00fcr jede Java-Installation einmalig das Kommando <code>java -Xshare:dump<\/code> ausf\u00fchren, wodurch die Shared-Archive-Datei <code>classes.jsa<\/code> generiert wurde.<\/p>\n\n\n\n<p>Mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/341\" target=\"_blank\">JDK Enhancement Proposal 341<\/a> wird das JDK auf 64-Bit-Architekturen ab sofort mitsamt dieser Datei ausgeliefert, so dass die Ausf\u00fchrung von <code>java -Xshare:dump<\/code> nicht mehr n\u00f6tig ist und Java-Anwendungen standardm\u00e4\u00dfig das Default-CDS-Archiv verwenden.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"abortable-mixed-collections-for-g1\">Abortable Mixed Collections for G1<\/h3>\n\n\n\n<p>Eines der Ziele des G1 Gargabe Collectors ist es, bei denjenigen Aufr\u00e4umarbeiten, die nicht parallel zur Anwendung erfolgen k\u00f6nnen, vorgegebene maximale Pausezeiten einzuhalten \u2013 also die Anwendung nicht l\u00e4nger als die vorgegebene Zeit zu stoppen.<\/p>\n\n\n\n<p>Beim G1 wird diese Zeit mit dem Parameter <code>-XX:MaxGCPauseMillis<\/code> festgelegt. Wird der Parameter nicht angegeben, liegt die maximale Pausezeit bei 200 ms.<\/p>\n\n\n\n<p>G1 verwendet eine Heuristik, um eine Menge von Heap-Regionen zu bestimmen, die w\u00e4hrend einer solchen \"Stop-the-World\"-Phase aufger\u00e4umt werden (das sogenannte \"Collection Set\").<\/p>\n\n\n\n<p>Insbesondere bei \"Mixed Collections\" (d. h. beim Aufr\u00e4umen von Regionen junger <em>und<\/em> alter Generationen) kann es \u2013 insbesondere, wenn sich das Verhalten der Anwendung ver\u00e4ndert \u2013 vorkommen, dass die Heuristik ein zu gro\u00dfes Collection Set bestimmt und damit die Anwendung l\u00e4nger unterbrochen wird als vorgesehen.<\/p>\n\n\n\n<p><a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/344\" target=\"_blank\">JDK Enhancement Proposal 344<\/a> optimiert die Mixed Collections dahingehend, dass bei wiederholtem \u00dcberschreiten der maximalen Pausezeit das Collection Set in einen obligatorischen und einen optionalen Teil aufgeteilt wird. Der obligatorische Teil wird ununterbrechbar ausgef\u00fchrt \u2013 und der optionale Teil in kleinen Schritten, bis die maximale Pausezeit erreicht ist.<\/p>\n\n\n\n<p>W\u00e4hrenddessen versucht der Algorithmus die Heuristik so anzupassen, dass sie baldm\u00f6glichst wieder Collection Sets bestimmt, die in der vorgegebenen Pausezeit abarbeitbar sind.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"promptly-return-unused-committed-memory-from-g1\">Promptly Return Unused Committed Memory from G1<\/h3>\n\n\n\n<p>In Umgebungen, in denen man f\u00fcr den tats\u00e4chlich genutzten Arbeitsspeicher bezahlt, ist es w\u00fcnschenswert, dass der Garbage Collector unbenutzten Speicherplatz schnell wieder an das Betriebssystem zur\u00fcckgibt.<\/p>\n\n\n\n<p>Der G1 Garbage Collector kann zwar Speicherplatz zur\u00fcckgeben, allerdings nur w\u00e4hrend der Garbage-Collection-Phase. Wenn jedoch die Heap-Belegung oder die aktuelle Rate der Objekt-Allokationen keinen Garbage-Collection-Zyklus triggert, wird auch kein Arbeitsspeicher zur\u00fcckgegeben.<\/p>\n\n\n\n<p>Nehmen wir an, wir haben eine Applikation, die nur einmal am Tag einen speicherintensiven Batch-Prozess ausf\u00fchrt, den Rest der Zeit aber ziemlich inaktiv ist. So gibt es nach Abarbeitung des Batch-Prozesses keinen Grund f\u00fcr einen Garbage-Collection-Zyklus, und wir bezahlen f\u00fcr den gr\u00f6\u00dften Teil des Tages f\u00fcr Arbeitsspeicher, in dem unbenutzte Objekte liegen (rot markierter Bereich):<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-half_600\"><img decoding=\"async\" width=\"600\" height=\"327\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/jep346-memory-usage-without-periodic-gc-v5-600x327.png\" alt=\"JEP 346: Speicherbelegung ohne periodische GCs\" class=\"wp-image-23720\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/jep346-memory-usage-without-periodic-gc-v5-600x327.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/jep346-memory-usage-without-periodic-gc-v5-224x122.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/jep346-memory-usage-without-periodic-gc-v5-336x183.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/jep346-memory-usage-without-periodic-gc-v5-504x275.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/jep346-memory-usage-without-periodic-gc-v5-672x366.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/jep346-memory-usage-without-periodic-gc-v5-400x218.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/jep346-memory-usage-without-periodic-gc-v5-800x436.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/jep346-memory-usage-without-periodic-gc-v5-944x514.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/jep346-memory-usage-without-periodic-gc-v5.png 1200w\" sizes=\"(max-width: 600px) 100vw, 600px\" \/><figcaption class=\"wp-element-caption\">JEP 346: Speicherbelegung ohne periodische GCs<\/figcaption><\/figure>\n<\/div>\n\n\n<p><a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/346\" target=\"_blank\">JEP 346<\/a> bietet eine L\u00f6sung f\u00fcr dieses Problem. Wenn die Anwendung inaktiv ist, wird in regelm\u00e4\u00dfigen Abst\u00e4nden ein paralleler Garbage-Collection-Zyklus gestartet, der ggf. nicht mehr ben\u00f6tigten Speicher wieder freigibt. <\/p>\n\n\n\n<p>Dieses Feature ist standardm\u00e4\u00dfig deaktiviert. Du kannst es aktivieren, indem du \u00fcber den Parameter <code>-XX:G1PeriodicGCInterval<\/code> ein Intervall in Millisekunden angibst, in dem G1 pr\u00fcfen soll, ob ein solcher Zyklus gestartet werden soll. Der Speicher wird so z\u00fcgig wieder zur\u00fcckgegeben:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-half_600\"><img decoding=\"async\" width=\"600\" height=\"327\" src=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/jep346-memory-usage-with-periodic-gc-v5-600x327.png\" alt=\"JEP 346: Speicherbelegung mit periodischen GCs\" class=\"wp-image-23721\" srcset=\"https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/jep346-memory-usage-with-periodic-gc-v5-600x327.png 600w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/jep346-memory-usage-with-periodic-gc-v5-224x122.png 224w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/jep346-memory-usage-with-periodic-gc-v5-336x183.png 336w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/jep346-memory-usage-with-periodic-gc-v5-504x275.png 504w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/jep346-memory-usage-with-periodic-gc-v5-672x366.png 672w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/jep346-memory-usage-with-periodic-gc-v5-400x218.png 400w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/jep346-memory-usage-with-periodic-gc-v5-800x436.png 800w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/jep346-memory-usage-with-periodic-gc-v5-944x514.png 944w, https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/10\/jep346-memory-usage-with-periodic-gc-v5.png 1200w\" sizes=\"(max-width: 600px) 100vw, 600px\" \/><figcaption class=\"wp-element-caption\">JEP 346: Speicherbelegung mit periodischen GCs<\/figcaption><\/figure>\n<\/div>\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"experimentelle-und-preview-features\">Experimentelle und Preview-Features<\/h2>\n\n\n\n<p>Dieser Abschnitt listet experimentelle und Preview-Features auf, also Features, die noch im Entwicklungsstadium sind und ggf. anhand von Feedback aus der Java-Community bis zum finalen Release noch ver\u00e4ndert werden.<\/p>\n\n\n\n<p>Anstatt detailliert auf diese Features einzugehen, werde ich auf die Java-Version verweisen, in der die jeweiligen Features als \"production-ready\" released werden.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"switch-expressions-preview\">Switch Expressions (Preview)<\/h3>\n\n\n\n<p>Dank <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/325\" target=\"_blank\">JDK Enhancement Proposal 325<\/a> k\u00f6nnen <code>switch<\/code>-Anweisungen vereinfacht werden, indem mehrere F\u00e4lle mit Kommata getrennt werden und mit der Pfeil-Notation die fehleranf\u00e4lligen <code>break<\/code>-Statements wegfallen k\u00f6nnen:<\/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\">switch<\/span> (day) {\n  <span class=\"hljs-keyword\">case<\/span> MONDAY, FRIDAY, SUNDAY -&gt; System.out.println(<span class=\"hljs-number\">6<\/span>);\n  <span class=\"hljs-keyword\">case<\/span> TUESDAY                -&gt; System.out.println(<span class=\"hljs-number\">7<\/span>);\n  <span class=\"hljs-keyword\">case<\/span> THURSDAY, SATURDAY     -&gt; System.out.println(<span class=\"hljs-number\">8<\/span>);\n  <span class=\"hljs-keyword\">case<\/span> WEDNESDAY              -&gt; System.out.println(<span class=\"hljs-number\">9<\/span>);\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>Dar\u00fcberhinaus k\u00f6nnen mit <code>switch<\/code>-<em>Ausdr\u00fccken<\/em> (\"expressions\") einer Variablen Fall-abh\u00e4ngige Werte zugewiesen werden:<\/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\">int<\/span> numLetters = <span class=\"hljs-keyword\">switch<\/span> (day) {\n  <span class=\"hljs-keyword\">case<\/span> MONDAY, FRIDAY, SUNDAY -&gt; <span class=\"hljs-number\">6<\/span>;\n  <span class=\"hljs-keyword\">case<\/span> TUESDAY                -&gt; <span class=\"hljs-number\">7<\/span>;\n  <span class=\"hljs-keyword\">case<\/span> THURSDAY, SATURDAY     -&gt; <span class=\"hljs-number\">8<\/span>;\n  <span class=\"hljs-keyword\">case<\/span> WEDNESDAY              -&gt; <span class=\"hljs-number\">9<\/span>;\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><code>switch<\/code>-<em>Ausdr\u00fccke<\/em> k\u00f6nnen auch mit der herk\u00f6mmlichen Schreibweise (mit Doppelpunkt und <code>break<\/code>) notiert werden. Dabei wird der zur\u00fcckzugebende Wert hinter dem <code>break<\/code>-Keyword angegeben:<\/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\">int<\/span> numLetters = <span class=\"hljs-keyword\">switch<\/span> (day) {\n  <span class=\"hljs-keyword\">case<\/span> MONDAY, FRIDAY, SUNDAY:\n    <span class=\"hljs-keyword\">break<\/span> <span class=\"hljs-number\">6<\/span>;\n  <span class=\"hljs-keyword\">case<\/span> TUESDAY:\n    <span class=\"hljs-keyword\">break<\/span> <span class=\"hljs-number\">7<\/span>;\n  <span class=\"hljs-keyword\">case<\/span> THURSDAY, SATURDAY:\n    <span class=\"hljs-keyword\">break<\/span> <span class=\"hljs-number\">8<\/span>;\n  <span class=\"hljs-keyword\">case<\/span> WEDNESDAY:\n    <span class=\"hljs-keyword\">break<\/span> <span class=\"hljs-number\">9<\/span>;\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>(Achtung: <code>break<\/code> wird im n\u00e4chsten Preview durch <code>yield<\/code> ersetzt werden.)<\/p>\n\n\n\n<p>Switch Expressions werden in <a href=\"\/de\/java\/java-14-features\/\">Java 14<\/a> produktionsreif sein. Alle Details \u00fcber sie findest du im <a href=\"\/de\/java\/switch-expressions\/\">Hauptartikel \u00fcber Switch Expressions<\/a>.<\/p>\n\n\n\n<p>Um Switch Expressions bereits in Java 12 einzusetzen, musst du sie entweder in deiner IDE aktivieren (in IntelliJ geht das \u00fcber <em>File\u2192Project Structure\u2192Project Settings\u2192Project\u2192Project language level<\/em>) oder mit dem Parameter <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=\"shenandoah-a-low-pause-time-garbage-collector-experimental\">Shenandoah: A Low-Pause-Time Garbage Collector (Experimental)<\/h3>\n\n\n\n<p>In <a rel=\"noopener\" href=\"\/de\/java\/java-11-features\/#ZGC_A_Scalable_Low-Latency_Garbage_Collector_Experimental\" target=\"_blank\">Java 11 wurde Oracles \"Z Garbage Collector\"<\/a> als experimentelles Feature vorgestellt.<\/p>\n\n\n\n<p>Mit Java 12 kommt ein weiterer Low-Latency Garbage Collector hinzu: der von Red Hat entwickelte \"Shenandoah\". Genau wie ZGC hat auch Shenandoah das Ziel die Pausezeiten von Full GCs zu minimieren.<\/p>\n\n\n\n<p>Du kannst Shenandoah \u00fcber folgende Option in der <code>java<\/code>-Befehlszeile aktivieren:<\/p>\n\n\n\n<p class=\"has-text-align-center\"><code>-XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC<\/code><\/p>\n\n\n\n<p>Shenandoah und ZGC werden in <a href=\"\/de\/java\/java-15-features\/#Shenandoah_A_Low-Pause-Time_Garbage_Collector\">Java 15<\/a> Produktionsreife erreichen. Im entsprechenden Teil dieser Serie werde ich beide Garbage Collectoren detaillierter beschreiben.<\/p>\n\n\n\n<p><em>(Dieses experimentelle Release ist im&nbsp;<a href=\"https:\/\/openjdk.org:443\/jeps\/189\" target=\"_blank\" rel=\"noopener\">JDK Enhancement Proposal 189<\/a>&nbsp;definiert.)<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"sonstige-aenderungen-in-java-12-die-man-als-java-entwickler-nicht-unbedingt-kennen-muss\">Sonstige \u00c4nderungen in Java 12 (die man als Java-Entwickler nicht unbedingt kennen muss)<\/h2>\n\n\n\n<p>In diesem Abschnitt liste ich \u00c4nderungen auf, die die t\u00e4gliche Arbeit der meisten Java-Entwicklerinnen und  -Entwickler nicht betreffen werden. Es ist aber sicherlich nicht verkehrt, die \u00c4nderungen einmal \u00fcberflogen zu haben.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"unicode-11\">Unicode 11<\/h3>\n\n\n\n<p>Nachdem in <a href=\"https:\/\/www.happycoders.eu\/de\/java\/java-11-features\/#Unicode_10\">Java 11 Support f\u00fcr Unicode 10<\/a> integriert wurde, wurde der Support in Java 12 auf Unicode 11 angehoben. Das bedeutet, dass insbesondere die Klassen <code>String<\/code> und <code>Character<\/code> mit den neuen Zeichen, Codebl\u00f6cken und Schriftsystemen umgehen k\u00f6nnen m\u00fcssen.<\/p>\n\n\n\n<p>Ein Beispiel dazu findest du im zuvor verlinkten Abschnitt \u00fcber Unicode 10.<\/p>\n\n\n\n<p><em>(F\u00fcr die Unterst\u00fctzung von Unicode 11 existiert kein JDK Enhancement Proposal.)<\/em> <\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"microbenchmark-suite\">Microbenchmark Suite<\/h3>\n\n\n\n<p>Bis dato wurden Microbenchmarks f\u00fcr die JDK-Klassenbibliothek als separates Projekt verwaltet. Diese Benchmarks messen regelm\u00e4\u00dfig die Leistung der JDK-Klassenbibliothek und werden z. B. verwendet um bei neuen Java-Releases sicherzustellen, dass JDK-Methoden nicht langsamer geworden sind.<\/p>\n\n\n\n<p>Mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/230\" target=\"_blank\">JDK Enhancement Proposal 230<\/a> wird die bestehende Sammlung an Microbenchmarks in den JDK-Quellcode verschoben, um die Ausf\u00fchrung und Weiter.entwicklung der Tests zu vereinfachen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"jvm-constants-api\">JVM Constants API<\/h3>\n\n\n\n<p>Im Konstantenpool (\"constant pool\") einer .class-Datei werden Konstanten gespeichert, die beim Compilieren einer .java-Datei anfallen. Das sind zum einen Konstanten, die im Java-Code definiert sind, wie z. B. der String \"Hello world!\", aber auch die Namen referenzierter Klassen und Methoden (z. B. \"java\/lang\/System\", \"out\" und \"println\"). Jede Konstante ist einer Nummer zugeordnet, auf die der Bytecode der .class-Datei referenziert.<\/p>\n\n\n\n<p>Der <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/334\" target=\"_blank\">JDK Enhancement Proposal 334<\/a> soll es erleichtern Java-Programme zu schreiben, die wiederum JVM-Bytecode lesen oder schreiben. Dazu werden neue Interfaces und Klassen zur Verf\u00fcgung gestellt, mit der die Konstanten des Constant Pools abgebildet werden k\u00f6nnen.<\/p>\n\n\n\n<p>Diese Interfaces und Klassen befinden sich im Paket <a rel=\"noopener\" href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/12\/docs\/api\/java.base\/java\/lang\/constant\/package-summary.html\" target=\"_blank\"><code>java.lang.constant<\/code><\/a> und bilden eine Hierarchie, die mit dem Interface <code>ConstantDesc<\/code> beginnt. Ein \"Hello World!\" bspw. wird durch die <code>String<\/code>-Klasse abgebildet, die seit Java 12 eben auch dieses Interface implementiert (genau wie <code>Integer<\/code>, <code>Long<\/code>, <code>Float<\/code> und <code>Double<\/code>).<\/p>\n\n\n\n<p>Komplizierter wird es bei Konstanten, die Referenzen auf Klassen und deren Methoden darstellen. Die Reflection-Klassen <code>Class<\/code> und <code>MethodHandle<\/code> k\u00f6nnen wir nicht verwenden, da wir die referenzierten Klassen und Methoden gar nicht unbedingt kennen, sondern eben nur deren Namen, Parameter und R\u00fcckgabewerte.<\/p>\n\n\n\n<p>Genau daf\u00fcr gibt es nun (u. a.) die Klassen <code><a rel=\"noopener\" href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/12\/docs\/api\/java.base\/java\/lang\/constant\/ClassDesc.html\" target=\"_blank\">ClassDesc<\/a><\/code>, um eine Klasse zu bezeichnen, und <code><a rel=\"noopener\" href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/12\/docs\/api\/java.base\/java\/lang\/constant\/MethodHandleDesc.html\" target=\"_blank\">MethodHandleDesc<\/a><\/code> und <code><a rel=\"noopener\" href=\"https:\/\/docs.oracle.com\/en\/java\/javase\/12\/docs\/api\/java.base\/java\/lang\/constant\/MethodTypeDesc.html\" target=\"_blank\">MethodTypeDesc<\/a><\/code>, um eine Methode zu bezeichnen.<\/p>\n\n\n\n<p>Weitere Details dieses doch eher exotischen Features w\u00fcrden den Rahmen dieses Artikels sprengen.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"one-aarch64-port-not-two\">One AArch64 Port, Not Two<\/h3>\n\n\n\n<p>Im JDK existieren bis dato zwei unterschiedliche Portierungen f\u00fcr 64-Bit ARM-CPUs: <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\"arm64\" \u2013 entwickelt von Oracle (als Erweiterung der 32-Bit-ARM-Portierung \"arm\")<\/li>\n\n\n\n<li>\"aarch64\" \u2013 zeitgleich, aber unabh\u00e4ngig entwickelt von Red Hat<\/li>\n<\/ul>\n\n\n\n<p>Mit dem <a rel=\"noopener\" href=\"https:\/\/openjdk.org:443\/jeps\/340\" target=\"_blank\">JDK Enhancement Proposal 340<\/a> wird der Port von Oracle entfernt, um die Entwicklungsresourcen auf eine Portierung zu konzentrieren.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" class=\"wp-block-heading\" id=\"vollstaendige-liste-aller-aenderungen-in-java-12\">Vollst\u00e4ndige Liste aller \u00c4nderungen in Java 12<\/h3>\n\n\n\n<p>Dieser Artikel hat alle Features von Java 12 vorgestellt, die in JDK Enhancement Proposals definiert sind, sowie Erweiterungen an der JDK-Klassenbibliothek, die keinem JEP zugeordnet sind.<\/p>\n\n\n\n<p>Eine vollst\u00e4ndige Liste aller \u00c4nderungen findest du in den&nbsp;<a href=\"https:\/\/www.oracle.com\/java\/technologies\/javase\/12-relnote-issues.html\" target=\"_blank\" rel=\"noopener\">offiziellen Java 12 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>Die \u00c4nderungen in Java 12 sind recht \u00fcberschaubar. Wir haben ein paar neue <code>String<\/code>- und <code>Files<\/code>-Methoden bekommen sowie den Teeing-Collector, mit dem wir einen Stream \u00fcber zwei Collectoren terminieren und deren Ergebnisse kombinieren k\u00f6nnen.<\/p>\n\n\n\n<p>Class-Data Sharing ist nun dank der auf 64-Bit-Systemen mitgelieferten <code>classes.jsa<\/code>-Shared-Archive-Datei standardm\u00e4\u00dfig aktiviert.<\/p>\n\n\n\n<p>Der G1 Garbage Collector kann Mixed Collections abbrechen, wenn diese zu lange dauern. Nicht mehr ben\u00f6tigten Speicher gibt er z\u00fcgig an das Betriebssystem zur\u00fcck.<\/p>\n\n\n\n<p>Mit Switch Expressions und dem Shenandoah Garbage Collector haven zwei experimentelle bzw. Preview-Features ebenfalls Einzug in Java 12 gehalten.<\/p>\n\n\n\n<p>Wenn dir der Artikel gefallen hat, hinterlasse mir gerne einen Kommentar oder teile den Artikel \u00fcber einen der Share-Buttons am Ende des Artikels.<\/p>\n\n\n\n<p>M\u00f6chtest du per E-Mail informiert werden, wenn der n\u00e4chste Teil der Serie ver\u00f6ffentlicht wird? Dann <a href=\"#\" data-formkit-toggle=\"d8ee997126\">klicke hier<\/a>, um dich f\u00fcr den <a href=\"#\" data-formkit-toggle=\"135d38e6d4\">HappyCoders-Newsletter<\/a> anzumelden.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Alle neuen Features von Java 12: neue String- und Files-Methoden, Teeing Collector, Default CDS Archives, G1-Optimierungen + mehr<\/p>\n","protected":false},"author":1,"featured_media":34279,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_seopress_robots_primary_cat":"none","_seopress_titles_title":"","_seopress_titles_desc":"Alle neuen Features von Java 12 mit Beispielen: neue String- und Files-Methoden, Teeing Collector, Default CDS Archives, G1-Optimierungen + mehr","_seopress_robots_index":"","_uag_custom_page_level_css":"","_wp_convertkit_post_meta":{"form":"-1","landing_page":"","tag":"0","restrict_content":"0"},"_metis_text_type":"standard","_metis_text_length":18886,"_post_count":0,"footnotes":""},"categories":[64],"tags":[176],"class_list":["post-23825","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-12-features.jpg",1770,986,false],"thumbnail":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-12-features.jpg",150,84,false],"medium":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-12-features.jpg",300,167,false],"medium_large":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-12-features.jpg",768,428,false],"large":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-12-features.jpg",1024,570,false],"feature_thumb_224":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-12-features-224x125.jpg",224,125,true],"feature_thumb_336":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-12-features-336x187.jpg",336,187,true],"feature_thumb_504":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-12-features-504x281.jpg",504,281,true],"feature_thumb_672":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-12-features-672x374.jpg",672,374,true],"half_400":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-12-features-400x223.jpg",400,223,true],"half_600":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-12-features-600x334.jpg",600,334,true],"full_800":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-12-features-800x446.jpg",800,446,true],"full_944":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-12-features-944x526.jpg",944,526,true],"full_1200":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-12-features-1200x668.jpg",1200,668,true],"wide_1180":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-12-features-1180x490.jpg",1180,490,true],"wide_1770":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-12-features-1770x735.jpg",1770,735,true],"1536x1536":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-12-features.jpg",1536,856,false],"2048x2048":["https:\/\/www.happycoders.eu\/wp-content\/uploads\/2021\/11\/java-12-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 12: neue String- und Files-Methoden, Teeing Collector, Default CDS Archives, G1-Optimierungen + mehr","public_identification_id":"3be957509f5044c4b7a956e1de601fa1","private_identification_id":"a7e302ed41064aafa99ab5ef36dc12fd","_links":{"self":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/23825","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=23825"}],"version-history":[{"count":13,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/23825\/revisions"}],"predecessor-version":[{"id":54309,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/posts\/23825\/revisions\/54309"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/media\/34279"}],"wp:attachment":[{"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/media?parent=23825"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/categories?post=23825"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.happycoders.eu\/de\/wp-json\/wp\/v2\/tags?post=23825"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}