39 neue Funktionen in Java 12

Aus einem wunderbaren Interview über Habré: „Simon Ritter hat von Anfang an an Java gearbeitet und tut dies weiterhin als stellvertretender technischer Direktor von Azul, einem Unternehmen, das an der virtuellen Maschine Zing JVM arbeitet, und einem der besten Müllsammler, C4 (Continuously Concurrent Compacting) Sammler) »
Im Folgenden finden Sie eine Übersetzung seines Artikels über die neuen JDK 12-Funktionen und einige Schwierigkeiten, die bei der Migration auf einen neuen Build auftreten können.

Ich habe mehrere Blog-Beiträge geschrieben, in denen alle Änderungen für die neuesten Java-Versionen ( JDK 10 , JDK 11 ) aufgeführt sind. Ich werde jetzt die Schattenseiten von JDK 12 untersuchen und mich auf einige der Fallstricke konzentrieren, die Probleme verursachen können, wenn Sie die Anwendung auf diese Version portieren möchten.



JDK 12 hat die geringste Anzahl neuer Funktionen aus allen bisherigen Java-Versionen (ich habe 109 in JDK 10 und 90 in JDK 11 gezählt). Dies ist nicht schlecht - aufgrund von Veröffentlichungszyklen enthalten einige Versionen mehr Änderungen, andere weniger.


Ich werde neue Funktionen in offensichtliche logische Bereiche unterteilen: Java, Bibliotheken, JVMs und andere JDK-Funktionen.


Sprachänderungen


Die Funktion, die ich (und ich gehe davon aus, dass viele andere Personen) in JDK 12 am sichtbarsten ist, ist die neue switch-Anweisung ( JEP 325 ). Dies ist auch die erste Sprachänderung, die als Funktion für die „Vorschau“ verwendet wird. Die Idee der „Vorschau“ wurde Anfang 2018 im Rahmen von JEP 12 eingeführt . Dies ist im Wesentlichen eine Möglichkeit, Beta-Versionen neuer Funktionen mithilfe von Befehlszeilenoptionen zu aktivieren. Mithilfe der Vorschau können weiterhin Änderungen basierend auf dem Feedback der Benutzer vorgenommen und im schlimmsten Fall eine Funktion vollständig entfernt werden, wenn sie nicht ordnungsgemäß empfangen wurde. Der Schlüssel zur Vorschau von Funktionen liegt darin, dass sie nicht in der Java SE-Spezifikation enthalten sind. Über den neuen Schalter gibt es eine sehr gute Übersetzung auf Habré.
In JDK 12 ist ein Schalter zu einem Ausdruck geworden, der seinen „Inhalt“ auswertet, um ein Ergebnis zu erzielen. Ich werde sofort erklären, dass dies keine Auswirkungen auf die Abwärtskompatibilität hat. Sie müssen also keinen Code ändern, der switch als Operator verwendet.


Ich werde das Beispiel von JEP verwenden, da es einfach und klar ist:


Alter Schalter
int numLetters; switch (day) { case MONDAY: case FRIDAY: case SUNDAY: numLetters = 6; break; case TUESDAY: numLetters = 7; break; case THURSDAY: case SATURDAY: numLetters = 8; break; case WEDNESDAY: numLetters = 9; break; default: throw new IllegalStateException("Huh? " + day); } 

Wie Sie sehen können, ordnen wir den Wochentag dem Namen des variablen day und weisen dann den Wert numLetters . Jetzt, da switch ein Operator ist, können wir die Zuweisung einmal ausführen (wodurch die Wahrscheinlichkeit eines fehlerhaften Codes erheblich verringert wird), indem wir das Ergebnis der switch-Anweisung verwenden:


 int numLetters = switch (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case TUESDAY -> 7; case THURSDAY, SATURDAY -> 8; case WEDNESDAY -> 9; default -> throw new IllegalStateException("Huh? " + day); }; 

Sie werden schnell zwei Syntaxänderungen bemerken. OpenJDK-Entwickler stießen auf eine wenig bekannte Syntaxfunktion, die als durch Kommas getrennte Liste bezeichnet wird. Auch der Lambda-Ausdrucksoperator -> erleichtert die Rückgabe des Wertes. Sie können break mit einem Wert verwenden, wenn Sie dies wirklich möchten. Es gibt einige andere Details zu dieser Funktion, aber es ist wahrscheinlich einfacher, JEP zu lesen.


Bibliotheken


Es gibt eine Änderung, die ich sehr nützlich finde. Es gibt auch eine Reihe von sekundären.


Abschlag Sammler


Die Streams-API verfügt wie üblich über einen neuen Collector, der von der Collectors-Dienstprogrammklasse bereitgestellt wird. Ein neuer Kollektor kann mit der teeing() -Methode erhalten werden. Der Abschlagsammler führt drei Argumente an: zwei Sammler und eine Bifunktion. Um die Arbeit dieses Sammlers zu verstehen, empfehle ich diesen Artikel über Habré .
Um zu verstehen, wie er das macht, habe ich ein Diagramm gezeichnet:


Bild

Alle Werte aus dem Eingabestream werden an jeden Kollektor übergeben. Das Ergebnis jedes Kollektors wird als Argument an BiFunction übergeben und das Endergebnis generiert.


Ein einfaches Beispiel ist die Berechnung des Durchschnittswerts (ja, ich weiß, dass es dafür bereits Kollektoren gibt, wie beispielsweise averagingInt() , aber dies ist ein einfaches Beispiel, um das Konzept besser zu verstehen).


 /* Assume Collectors is statically imported */ double average = Stream.of(1, 4, 2, 7, 4, 6, 5) .collect(teeing( summingDouble(i -> i), counting(), (sum, n) -> sum / n) ); 

Der erste Kollektor berechnet die Summe des Eingabestreams und der zweite die Anzahl der Elemente. BiFunction dividiert die Summe durch die Anzahl der Elemente, um den Durchschnittswert zu erhalten.


java.io


InputStream skipNBytes(long n) - überspringt und verwirft genau n Bytes aus dem Eingabestream InputStream. Wenn n Null oder weniger ist, werden Bytes nicht übersprungen.


java.lang


Es wurde ein neues Paket veröffentlicht, java.lang.constant, das Teil der konstanten JVM-API JEP 334 ist .


Jede Java-Klassendatei verfügt über einen persistenten Pool, in dem Operanden für Bytecode-Anweisungen in der Klasse gespeichert sind. Für Entwickler ist es schwierig, Klassendateien zu bearbeiten, da beim Laden von Klassen Probleme auftreten. Die konstante JVM-API bietet symbolische Referenztypen zur Beschreibung jeder Form einer Konstante (Klasse, ladbare Konstante, MethodHandle , MethodHandle Konstante, MethodType Konstante).


Es beeinflusste auch mehrere andere Klassen. Alle folgenden Klassen haben jetzt eine Methode describeConstable() :


  • Klasse
  • Doppel
  • Aufzählung
  • Float
  • Ganzzahl
  • Lang
  • String
  • Methodenhandle
  • MethodType
  • Varhandle

Als Brite finde ich das ziemlich lustig. Der Begriff Constable, describeConstable wird seit dem 11. Jahrhundert verwendet, und so beziehen wir uns oft auf Polizisten. Es ist auch der Name des berühmten Künstlers John Constable aus dem 18. Jahrhundert. Ich frage mich daher, ob die Methode verifyTurner describeTurner() in einer zukünftigen Version verfügbar sein wird. Offensichtlich handelt es sich in diesem Fall um eine Abkürzung der Constant Table , die nicht mit einem Juristen oder Landschaftsmaler verwandt ist.


Die folgenden Klassen enthalten jetzt die Methode resolveConstantDesc() :


  • Doppel
  • Enum.EnumDesc
  • Float
  • Ganzzahl
  • Lang
  • String

java.lang.Character


Innere Klassen wurden aktualisiert, um neue Unicode-Blöcke aufzunehmen. Ich möchte immer sehen, was die Leute gefunden haben, um Unicode hinzuzufügen. Hier einige Beispiele:


  • Schachsymbole
  • Maya-Zahlen
  • Sogdisch ist eine ostiranische Sprache, die im 11. Jahrhundert nicht mehr verwendet wurde.
  • Old Sogdian ist eine ältere (und, wie ich vermute, noch eingeschränktere) Version von Sogdian

java.lang.Class


arrayType() gibt Class für den Typ des Arrays zurück, dessen Komponententyp von dieser Class beschrieben wird. Dies kann mit jshell überprüft werden:


 jshell> (new String[2]).getClass().getName() $11 ==> "[Ljava.lang.String;" jshell> (new String[2]).getClass().arrayType() $12 ==> class [[Ljava.lang.String; jshell> "foo".getClass().arrayType() $15 ==> class [Ljava.lang.String; 

Ich bin mir nicht ganz sicher, was die Bedeutung dieser Methode ist, da sie lediglich dem Typ, den diese Klasse darstellt, eine Class hinzufügt.


componentType() , wie getComponentType() . Die Frage lautet: Warum eine redundante Methode hinzufügen?


descriptorString() - gibt wieder das gleiche Ergebnis wie getName() . Dies ist jedoch erforderlich, da Class jetzt die TypeDescriptor Schnittstelle implementiert, die der neuen konstanten JVM-API zugeordnet ist.


lava.lang.String


indent() - Fügt einer Zeichenfolge eine Reihe führender Leerzeichen hinzu. Wenn der Parameter negativ ist, wird diese Anzahl führender Leerzeichen entfernt (falls möglich).


transform() - Wendet die bereitgestellte Funktion auf eine Zeichenfolge an. Das Ergebnis ist möglicherweise keine Zeichenfolge.


java.lang.invoke


VarHandle jetzt toString() , um eine kompakte Beschreibung zurückzugeben.


java.net.SecureCacheResponse und java.net.ssl.HttpsConnection haben eine neue Methode, getSSLSession() die Optional SSLSession die in der Verbindung verwendete SSLSession enthält.


java.nio.files


Die Files Klasse verfügt über eine neue Methode, mismatch() , die die Position des ersten Mismatch-Bytes im Inhalt von zwei Dateien findet und zurückgibt, oder -1L, wenn keine Mismatch vorliegt.


java.text


Es gibt eine neue Klasse CompactNumberFormat . Dies ist eine Unterklasse von NumberFormat , die eine Dezimalzahl in kompakter Form formatiert. Ein Beispiel für eine kompakte Form - 1M statt 1000000 - erfordert zwei statt neun Zeichen. NumberFormat und java.text.spi.NumberFormatProvider wurden um die neue Methode getCompactNumberInstance() . Es gibt auch eine neue Aufzählung, NumberFormatStyle die zwei Bedeutungen hat: LONG und SHORT.


java.util.concurrent


CompletionStage enthält jetzt mehrere überladene Formulare mit drei Methoden:


  • ausnahmsweise asynchron
  • außergewöhnlich komponieren
  • außergewöhnlichComposeAsync

Diese Methoden erweitern die Möglichkeiten, eine neue CompletionStage aus einer vorhandenen zu erstellen, CompletionStage wenn die aktuelle mit einer Ausnahme endet. Weitere Informationen finden Sie in der API-Dokumentation.


javax.crypto


Die Cipher Klasse verfügt über eine neue toString() -Methode, die eine Zeichenfolge zurückgibt, die die Cipher Transformation, den Modus und den Anbieter enthält.


javax.naming.ldap.spi


Dies ist ein neues Paket in JDK 12, das zwei Klassen enthält: LdapDnsProvider , die Anbieterklasse für DNS-Suchvorgänge während LDAP-Vorgängen, und LdapDnsProviderResults die das DNS- LdapDnsProviderResults für die LDAP-URL kapselt.


Schaukel


Swing wird noch aktualisiert! Ja, filechooser.FileSystemView verfügt jetzt über eine neue Methode getChooserShortcutPanelFiles() . Es gibt ein Array von Dateien zurück, die die Werte darstellen, die standardmäßig in der Verknüpfungsleiste für die Dateiauswahl angezeigt werden sollen.


JVM-Änderungen


JEP 189: Shenandoah: Müllsammler mit geringer Pause


Shenandoah ist ein 2014 von Red Hat angekündigtes Forschungsprojekt, das sich auf Anwendungsanforderungen mit geringer Latenz für die Speicherverwaltung in der JVM konzentriert. Seine Ziele sind eine maximale Pausenzeit von 1..10 ms für einen Haufen von mehr als 20 GB ( Daher ist es nicht für kleine Anwendungen gedacht - Wie einer der Entwickler von Shenandoah antwortete , ist dies nicht der Fall und es leistet hervorragende Arbeit bei kleinen Anwendungen. Dieser Kollektor arbeitet parallel zu Anwendungsthreads. Vermeiden Sie daher die Probleme, die bei den meisten Garbage Collectors auftreten.


JEP 344: Gemischte G1-Sammlungen


Diese Änderung soll das Verhalten des G1-Kollektors verbessern, wenn er das festgelegte Verzögerungsziel erreicht. G1 unterteilt den Heap-Raum (sowohl alt als auch alt) in Regionen. Die Idee ist, dass Sie in der alten Generation keinen Müll in einem Arbeitsgang sammeln müssen. Wenn G1 Müll sammeln muss, wählt es die Regionen aus, die es definiert. Dies wird als Sammlungskit bezeichnet. Vor JDK 12, als die Arbeiten am Set begannen, mussten alle Arbeiten im Wesentlichen als atomare Operation abgeschlossen werden. Das Problem war, dass sich der Sammlungssatz manchmal aufgrund von Änderungen bei der Verwendung des Heapspeichers durch die Anwendung als zu groß herausstellte und zu viel Zeit zum Sammeln benötigte, was dazu führte, dass eine Pausenzeit nicht erreicht wurde.


Wenn G1 in JDK 12 diese Situation erkennt, wird die Datenerfassung zur Hälfte unterbrochen, wenn dies die Fähigkeit der Anwendung nicht beeinträchtigt, weiterhin Speicherplatz für neue Objekte zuzuweisen. Der Nettoeffekt von G1 ist besser, wenn eine kurze Pausenzeit erreicht ist.


JEP 346: Geben Sie schnell nicht verwendeten zugewiesenen Speicher von G1 zurück


Dies ist eine weitere Leistungsverbesserung für G1, aber eine andere hängt damit zusammen, wie die JVM mit dem Rest des Systems interagiert. Offensichtlich wird Speicher für den JVM-Heap benötigt, und beim Start wird Speicher vom virtuellen Speicherzuweiser des Betriebssystems angefordert. Wenn die Anwendung gestartet wird, kann es vorkommen, dass die für den Heap erforderliche Speichermenge abnimmt und ein Teil des zugewiesenen Speichers zur Verwendung durch andere Anwendungen an das Betriebssystem zurückgegeben werden kann.


G1 tut dies bereits, kann dies jedoch nur an einer von zwei Stellen tun. Erstens während einer vollständigen Sammlung und zweitens während eines der parallelen Zyklen. G1 versucht, keine vollständige Erfassung durchzuführen, und bei geringer Speichernutzung kann es zwischen den Erfassungszyklen zu erheblichen Zeiträumen kommen. Dies führt dazu, dass G1 einen festen Speicher für eine lange Zeit behalten kann.


In JDK 12 versucht G1 regelmäßig, eine parallele Schleife fortzusetzen oder auszuführen, während die Anwendung inaktiv ist, um die allgemeine Verwendung des Java-Heaps zu bestimmen. Nicht verwendeter Speicher kann zeitnaher und vorhersehbarer an das Betriebssystem zurückgegeben werden.


Mit dem neuen Befehlszeilenflag -XX:G1PeriodicGCInterval kann die Anzahl der Millisekunden zwischen den Überprüfungen festgelegt werden.


Diese Funktion führt zu einer konservativeren Verwendung des JVM-Speichers für Anwendungen, die längere Zeit nicht verwendet wurden.


Weitere neue JDK-Funktionen


JEP 230: Microbenchmarking Kit


Java Microbenchmarking Harness (JMH) wurde von Alexey Shipilev bei Oracle entwickelt und bietet eine umfangreiche Plattform für die Entwicklung von Leistungstests für Java-Anwendungen. Alexey hat hervorragende Arbeit geleistet und Menschen dabei geholfen, viele einfache Fehler zu vermeiden, die sie bei der Analyse der Anwendungsleistung machen: Aufwärmen, Ausnahmen vermeiden usw.


Jetzt kann JMH in OpenJDK aufgenommen werden. Jeder, der daran interessiert ist, am JDK selbst zu arbeiten und den Code zu ändern, kann damit die Leistung vor und nach den Änderungen sowie die Leistung in verschiedenen Versionen vergleichen. Eine Reihe von Tests ist enthalten, um das Testen zu ermöglichen. Das Design von JMH ist so, dass es einfach ist, neue Tests dort hinzuzufügen, wo sie benötigt werden.


JEP 340: Ein Aarch64-Port, nicht zwei


OpenJDK verfügt über zwei Ports für die Arm64-Architektur, einen von Oracle und einen von Red Hat. Da dies nicht erforderlich war und Oracle die Unterstützung von Arm für seine JDK-Binärdateien eingestellt hat, wurde beschlossen, nur den Red Hat-Port zu verwenden, der noch unterstützt und entwickelt wird.


JEP 341: Standard-CDS-Archive


Die Data Sharing (CDS) -Klasse war früher eine kommerzielle Funktion in Oracle JDK. Mit einem kürzlich in JDK 11 vorgenommenen Übergang, um alle funktionalen Unterschiede zwischen Oracle JDK und OpenJDK zu beseitigen, wurde es in OpenJDK aufgenommen.


Um CDS verwenden zu können, benötigen Sie ein Archiv, das für Klassen erstellt wurde, die beim Start der Anwendung geladen werden. JDK 12 für 64-Bit-Plattformen enthält jetzt die Datei classes.jsa im Verzeichnis lib/server . Dies ist das CDS-Archiv für "Standardklassen". Ich gehe davon aus, dass dies alle öffentlichen Klassen in JDK-Modulen bedeutet. Ich konnte keinen Weg finden, es auszupacken, um es zu überprüfen. Da CDS standardmäßig aktiviert ist, was der Option -Xshare:auto in der Befehlszeile entspricht, profitieren Benutzer von verbesserten Startzeiten der Anwendung.


Schlussfolgerungen


JDK 12 bietet eine kleine Anzahl neuer Funktionen und APIs, wobei die switch für Entwickler am interessantesten ist. G1-Benutzer werden die Leistungsverbesserungen sicherlich zu schätzen wissen.


Mit der neuen Version der Version würde ich allen Benutzern empfehlen, ihre Anwendungen in dieser Version zu testen. Wenn Sie inkrementelle Änderungen im Auge behalten, können Sie Überraschungen vermeiden, wenn Sie sich für die nächste Version des langfristigen Supports entscheiden.


Wir haben kostenlose JDK 12- Builds für die Zulu Community Edition , die Sie beim Testen unterstützen. Probieren Sie sie unbedingt aus.

Source: https://habr.com/ru/post/de446590/


All Articles