Java 9 Neue Funktionen

Java 9 Neue Funktionen

1. Überblick

Java 9 wird mit einem umfangreichen Funktionsumfang geliefert. Obwohl es keine neuen Sprachkonzepte gibt, sind neue APIs und Diagnosebefehle für Entwickler auf jeden Fall interessant.

In diesem Artikel werden wir uns einige der neuen Funktionen auf hoher Ebene genauer ansehen. Eine vollständige Liste der neuen Funktionen ist inhere verfügbar.

2. Modulares System - Puzzle-Projekt

Beginnen wir mit dem Großen - der Modularität der Java-Plattform.

Ein modulares System bietet ähnliche Funktionen wie das OSGi-Framework. Module haben ein Abhängigkeitskonzept, können eine öffentliche API exportieren und Implementierungsdetails verborgen / privat halten.

Eine der Hauptmotive hierbei ist die Bereitstellung einer modularen JVM, die auf Geräten mit viel weniger verfügbarem Speicher ausgeführt werden kann. Die JVM kann nur mit den Modulen und APIs ausgeführt werden, die von der Anwendung benötigt werden. Inthis link finden Sie eine Beschreibung dieser Module.

Außerdem können interne JVM-APIs (Implementierungs-APIs) wiecom.sun.* nicht mehr über den Anwendungscode aufgerufen werden.

Einfach ausgedrückt, werden die Module in einer Datei namensmodule-info.java beschrieben, die sich oben in der Java-Code-Hierarchie befindet:

module com.example.java9.modules.car {
    requires com.example.java9.modules.engines;
    exports com.example.java9.modules.car.handling;
}

Für unser Modulcar muss das Modulengine ausgeführt und ein Paket fürhandling exportiert werden.

Weitere Informationen finden Sie unter OpenJDKProject Jigsaw: Module System Quick-Start Guide.

3. Ein neuer HTTP-Client

Ein lang erwarteter Ersatz der altenHttpURLConnection.

Die neue API befindet sich unter dem Paketjava.net.http.

Es sollte sowohlHTTP/2 protocol als auchWebSocket Handshake unterstützen, wobei die Leistung mit denApache HttpClient,Netty undJetty vergleichbar sein sollte.

Werfen Sie einen Blick auf diese neue Funktionalität, indem Sie eine einfache HTTP-Anfrage erstellen und senden.

Update: DieHTTP Client JEP werden in das Inkubator-Modul verschoben, sodass sie im Paketjava.net.http nicht mehr verfügbar sind und stattdessen unterjdk.incubator.http. verfügbar sind

3.1. Schnelle GET-Anfrage

Die API verwendet das Builder-Muster, was die schnelle Verwendung sehr einfach macht:

HttpRequest request = HttpRequest.newBuilder()
  .uri(new URI("https://postman-echo.com/get"))
  .GET()
  .build();

HttpResponse response = HttpClient.newHttpClient()
  .send(request, HttpResponse.BodyHandler.asString());

4. Prozess-API

Die Prozess-API wurde für die Steuerung und Verwaltung von Betriebssystemprozessen verbessert.

4.1. Prozessinformationen

Die Klassejava.lang.ProcessHandle enthält die meisten neuen Funktionen:

ProcessHandle self = ProcessHandle.current();
long PID = self.getPid();
ProcessHandle.Info procInfo = self.info();

Optional args = procInfo.arguments();
Optional cmd =  procInfo.commandLine();
Optional startTime = procInfo.startInstant();
Optional cpuUsage = procInfo.totalCpuDuration();

Die Methodecurrent gibt ein Objekt zurück, das einen Prozess darstellt, bei dem derzeit JVM ausgeführt wird. Die UnterklasseInfo enthält Details zum Prozess.

4.2. Prozesse zerstören

Stoppen Sie jetzt alle laufenden untergeordneten Prozesse mitdestroy():

childProc = ProcessHandle.current().children();
childProc.forEach(procHandle -> {
    assertTrue("Could not kill process " + procHandle.getPid(), procHandle.destroy());
});

5. Kleine Sprachänderungen

5.1. Try-With-Resources

In Java 7 erfordert die Syntax vontry-with-resources, dass für jede von der Anweisung verwaltete Ressource eine neue Variable deklariert wird.

In Java 9 gibt es eine zusätzliche Verfeinerung: Wenn die Ressource von einer finalen oder effektiv finalen Variablen referenziert wird, kann eine try-with-resources-Anweisung eine Ressource verwalten, ohne dass eine neue Variable deklariert wird:

MyAutoCloseable mac = new MyAutoCloseable();
try (mac) {
    // do some stuff with mac
}

try (new MyAutoCloseable() { }.finalWrapper.finalCloseable) {
   // do some stuff with finalCloseable
} catch (Exception ex) { }

5.2. Diamond Operator Extension

Jetzt können wir den Diamantoperator in Verbindung mit anonymen inneren Klassen verwenden:

FooClass fc = new FooClass<>(1) { // anonymous inner class
};

FooClass fc0 = new FooClass<>(1) {
    // anonymous inner class
};

FooClass fc1 = new FooClass<>(1) { // anonymous inner class
};

5.3. Private Methode der Schnittstelle

Schnittstellen in der kommenden JVM-Version könnenprivate-Methoden haben, mit denen lange Standardmethoden aufgeteilt werden können:

interface InterfaceWithPrivateMethods {

    private static String staticPrivate() {
        return "static private";
    }

    private String instancePrivate() {
        return "instance private";
    }

    default void check() {
        String result = staticPrivate();
        InterfaceWithPrivateMethods pvt = new InterfaceWithPrivateMethods() {
            // anonymous class
        };
        result = pvt.instancePrivate();
    }
}}

6. JShell-Befehlszeilentool

JShell ist eine Read-Eval-Print-Schleife - kurz REPL.

Einfach ausgedrückt ist es ein interaktives Tool zum Auswerten von Deklarationen, Anweisungen und Ausdrücken von Java zusammen mit einer API. Dies ist sehr praktisch zum Testen kleiner Codefragmente, für die ansonsten eine neue Klasse mit der Methodemainerstellt werden muss.

Die ausführbare Datei vonjshellelbst befindet sich im Ordner von<JAVA_HOME>/bin:

jdk-9\bin>jshell.exe
|  Welcome to JShell -- Version 9
|  For an introduction type: /help intro
jshell> "This is my long string. I want a part of it".substring(8,19);
$5 ==> "my long string"

Die interaktive Shell bietet Verlauf und automatische Vervollständigung. Es bietet auch Funktionen wie das Speichern und Laden von Dateien, alle oder einige der schriftlichen Anweisungen:

jshell> /save c:\develop\JShell_hello_world.txt
jshell> /open c:\develop\JShell_hello_world.txt
Hello JShell!

Code-Schnipsel werden beim Laden der Datei ausgeführt.

7. JCMD-Unterbefehle

Lassen Sie uns einige der neuen Unterbefehle imjcmd Kommandozeilenprogramm erkunden. Wir erhalten eine Liste aller in die JVM geladenen Klassen und ihrer Vererbungsstruktur.

Im folgenden Beispiel sehen wir die Hierarchie vonjava.lang.Socket, die in JVM geladen sind und Eclipse Neon ausführen:

jdk-9\bin>jcmd 14056 VM.class_hierarchy -i -s java.net.Socket
14056:
java.lang.Object/null
|--java.net.Socket/null
|  implements java.io.Closeable/null (declared intf)
|  implements java.lang.AutoCloseable/null (inherited intf)
|  |--org.eclipse.ecf.internal.provider.filetransfer.httpclient4.CloseMonitoringSocket
|  |  implements java.lang.AutoCloseable/null (inherited intf)
|  |  implements java.io.Closeable/null (inherited intf)
|  |--javax.net.ssl.SSLSocket/null
|  |  implements java.lang.AutoCloseable/null (inherited intf)
|  |  implements java.io.Closeable/null (inherited intf)

Der erste Parameter des Befehlsjcmdist die Prozess-ID (PID) der JVM, auf der der Befehl ausgeführt werden soll.

Ein weiterer interessanter Unterbefehl istset_vmflag. Wir können einige JVM-Parameter online ändern, ohne den JVM-Prozess neu starten und seine Startparameter ändern zu müssen.

Sie können alle verfügbaren VM-Flags mit dem Unterbefehljcmd 14056 VM.flags -all ermitteln

8. Bildauflösungs-API mit mehreren Auflösungen

Die Schnittstellejava.awt.image.MultiResolutionImage kapselt eine Reihe von Bildern mit unterschiedlichen Auflösungen in ein einzelnes Objekt. Wir können eine auflösungsspezifische Bildvariante basierend auf einer bestimmten DPI-Metrik und einer Reihe von Bildtransformationen abrufen oder alle Varianten im Bild abrufen.

Diejava.awt.Graphics-Klasse erhält eine Variante aus einem Bild mit mehreren Auflösungen basierend auf der aktuellen Anzeige-DPI-Metrik und allen angewendeten Transformationen.

Die Klassejava.awt.image.BaseMultiResolutionImage bietet eine grundlegende Implementierung:

BufferedImage[] resolutionVariants = ....
MultiResolutionImage bmrImage
  = new BaseMultiResolutionImage(baseIndex, resolutionVariants);
Image testRVImage = bmrImage.getResolutionVariant(16, 16);
assertSame("Images should be the same", testRVImage, resolutionVariants[3]);

9. Variable Griffe

Die API befindet sich unterjava.lang.invoke und besteht ausVarHandle undMethodHandles. Es bietet Äquivalente vonjava.util.concurrent.atomic- undsun.misc.Unsafe-Operationen für Objektfelder und Array-Elemente mit ähnlicher Leistung.

Mit Java 9 Modular System ist der Zugriff aufsun.misc.Unsafe über den Anwendungscode nicht möglich.

10. Publish-Subscribe Framework

Die Klassejava.util.concurrent.Flow bietet Schnittstellen, die das Publish-Subscribe-Framework vonReactive Streamsunterstützen. Diese Schnittstellen unterstützen die Interoperabilität zwischen mehreren asynchronen Systemen, die auf JVMs ausgeführt werden.

Wir können die DienstprogrammklasseSubmissionPublisher verwenden, um benutzerdefinierte Komponenten zu erstellen.

11. Einheitliche JVM-Protokollierung

Mit dieser Funktion wird ein gemeinsames Protokollierungssystem für alle Komponenten der JVM eingeführt. Es stellt die Infrastruktur für die Protokollierung bereit, fügt jedoch nicht die tatsächlichen Protokollierungsaufrufe von allen JVM-Komponenten hinzu. Es wird auch keine Protokollierung zu Java-Code im JDK hinzugefügt.

Das Protokollierungsframework definiert eine Menge vontags - zum Beispielgc,compiler,threads usw. Wir können den Befehlszeilenparameter-Xlog verwenden, um die Protokollierung während des Startvorgangs zu aktivieren.

Protokollieren Sie Nachrichten, die mit dem Tag "gc" markiert sind, auf der Ebene "Debug" in einer Datei mit dem Namen "gc.txt" ohne Dekorationen:

java -Xlog:gc=debug:file=gc.txt:none ...

-Xlog:help gibt mögliche Optionen und Beispiele aus. Die Protokollierungskonfiguration kann zur Laufzeit mit dem Befehljcmdgeändert werden. Wir werden GC-Protokolle auf info setzen und sie in eine Datei umleiten - gc_logs:

jcmd 9615 VM.log output=gc_logs what=gc

12. Neue APIs

12.1. Unveränderliches Set

java.util.Set.of() - Erstellt eine unveränderliche Menge bestimmter Elemente. In Java 8 würde das Erstellen eines Satzes aus mehreren Elementen mehrere Codezeilen erfordern. Jetzt können wir es so einfach machen wie:

Set strKeySet = Set.of("key1", "key2", "key3");

Die von dieser Methode zurückgegebenenSet sind interne JVM-Klassen:java.util.ImmutableCollections.SetN, die publicjava.util.AbstractSet erweitern. Es ist unveränderlich - wenn wir versuchen, Elemente hinzuzufügen oder zu entfernen, wird einUnsupportedOperationException ausgelöst.

Mit derselben Methode können Sie auch ein gesamtes Array inSet konvertieren.

12.2. Optional zum Streamen

java.util.Optional.stream() bietet uns eine einfache Möglichkeit, die Leistung von Streams für optionale Elemente zu nutzen:

List filteredList = listOfOptionals.stream()
  .flatMap(Optional::stream)
  .collect(Collectors.toList());

13. Fazit

Java 9 wird mit einer modularen JVM und vielen weiteren neuen und vielfältigen Verbesserungen und Funktionen geliefert.

Sie finden den Quellcode für die Beispieleover on GitHub.