Nuevas funciones de Java 9

1. Información general

Java 9 viene con un rico conjunto de funciones. Aunque no hay nuevos conceptos de lenguaje, las nuevas API y comandos de diagnóstico definitivamente serán interesantes para los desarrolladores.

En este artículo vamos a echar un vistazo rápido y de alto nivel a algunas de las nuevas funciones; una lista completa de nuevas funciones está disponible aquí.

2. Sistema modular - Proyecto de rompecabezas

Comencemos con el más grande: llevar la modularidad a la plataforma Java.

Un sistema modular proporciona capacidades similares al sistema del marco OSGi. Los módulos tienen un concepto de dependencias, pueden exportar una API pública y mantener los detalles de implementación ocultos / privados.

Una de las principales motivaciones aquí es proporcionar JVM modular, que puede ejecutarse en dispositivos con mucha menos memoria disponible. La JVM podría ejecutarse solo con los módulos y API que requiere la aplicación. Consulte este enlace para obtener una descripción de estos módulos.

Además, las API internas (de implementación) de JVM como com.sun. * Ya no son accesibles desde el código de la aplicación.

En pocas palabras, los módulos se describirán en un archivo llamado module-info.java ubicado en la parte superior de la jerarquía de código de Java:

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

Nuestro carro modular requiere un motor modular para funcionar y exporta un paquete para su manipulación .

Para obtener un ejemplo más detallado, consulte OpenJDK Project Jigsaw: Guía de inicio rápido del sistema de módulos.

3. Un nuevo cliente HTTP

Un reemplazo largamente esperado del antiguo HttpURLConnection .

La nueva API se encuentra en el paquete java.net.http .

Debería admitir tanto el protocolo HTTP / 2 como el protocolo de enlace WebSocket, con un rendimiento comparable al de Apache HttpClient, Netty y Jetty.

Echemos un vistazo a esta nueva funcionalidad creando y enviando una simple solicitud HTTP.

Actualización: el HTTP Client JEP se está moviendo al módulo Incubator, por lo que ya no está disponible en el paquete java.net.http y, en su lugar, está disponible en jdk.incubator.http.

3.1. Solicitud GET rápida

La API usa el patrón Builder, que lo hace realmente fácil de usar rápidamente:

HttpRequest request = HttpRequest.newBuilder() .uri(new URI("//postman-echo.com/get")) .GET() .build(); HttpResponse response = HttpClient.newHttpClient() .send(request, HttpResponse.BodyHandler.asString()); 

4. API de proceso

La API de procesos se ha mejorado para controlar y gestionar los procesos del sistema operativo.

4.1. Procesar informacion

La clase java.lang.ProcessHandle contiene la mayoría de las nuevas funcionalidades:

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();

El método actual devuelve un objeto que representa un proceso de JVM en ejecución. La subclase Info proporciona detalles sobre el proceso.

4.2. Procesos de destrucción

Ahora, detengamos todos los procesos secundarios en ejecución usando destroy () :

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

5. Pequeñas modificaciones del idioma

5.1. Probar con recursos

En Java 7, la sintaxis try-with-resources requiere que se declare una nueva variable para cada recurso administrado por la declaración.

En Java 9 hay un refinamiento adicional: si el recurso es referenciado por una variable final o efectivamente final, una declaración try-with-resources puede administrar un recurso sin que se declare una nueva variable:

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. Extensión del operador de diamantes

Ahora podemos usar el operador de diamante junto con clases internas anónimas:

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. Método privado de interfaz

Las interfaces en la próxima versión de JVM pueden tener métodos privados , que se pueden usar para dividir métodos predeterminados largos:

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. Herramienta de línea de comandos JShell

JShell es un ciclo de lectura-evaluación-impresión - REPL para abreviar.

En pocas palabras, es una herramienta interactiva para evaluar declaraciones, declaraciones y expresiones de Java, junto con una API. Es muy conveniente para probar pequeños fragmentos de código, que de lo contrario requieren la creación de una nueva clase con el método principal .

El ejecutable jshell en sí mismo se puede encontrar en la carpeta / 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"

The interactive shell comes with history and auto-completion; it also provides functionality like saving to and loading from files, all or some of the written statements:

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

Code snippets are executed upon file loading.

7. JCMD Sub-Commands

Let's explore some of the new subcommands in jcmd command line utility. We will get a list of all classes loaded in the JVM and their inheritance structure.

In the example below we can see the hierarchy of java.lang.Socket loaded in JVM running Eclipse Neon:

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) 

The first parameter of jcmd command is the process id (PID) of the JVM on which we want to run the command.

Another interesting subcommand is set_vmflag. We can modify some JVM parameters online, without the need of restarting the JVM process and modifying its startup parameters.

You can find out all the available VM flags with subcommand jcmd 14056 VM.flags -all

8. Мulti-Resolution Image API

The interface java.awt.image.MultiResolutionImage encapsulates a set of images with different resolutions into a single object. We can retrieve a resolution-specific image variant based on a given DPI metric and set of image transformations or retrieve all of the variants in the image.

The java.awt.Graphics class gets variant from a multi-resolution image based on the current display DPI metric and any applied transformations.

The class java.awt.image.BaseMultiResolutionImage provides basic implementation:

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 Handles

The API resides under java.lang.invoke and consists of VarHandle and MethodHandles. It provides equivalents of java.util.concurrent.atomic and sun.misc.Unsafe operations upon object fields and array elements with similar performance.

With Java 9 Modular system access to sun.misc.Unsafe will not be possible from application code.

10. Publish-Subscribe Framework

The class java.util.concurrent.Flow provides interfaces that support the Reactive Streams publish-subscribe framework. These interfaces support interoperability across a number of asynchronous systems running on JVMs.

We can use utility class SubmissionPublisher to create custom components.

11. Unified JVM Logging

This feature introduces a common logging system for all components of the JVM. It provides the infrastructure to do the logging, but it does not add the actual logging calls from all JVM components. It also does not add logging to Java code in the JDK.

The logging framework defines a set of tags – for example, gc, compiler, threads, etc. We can use the command line parameter -Xlog to turn on logging during startup.

Let's log messages tagged with ‘gc' tag using ‘debug' level to a file called ‘gc.txt' with no decorations:

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

-Xlog:help will output possible options and examples. Logging configuration can be modified runtime using jcmd command. We are going to set GC logs to info and redirect them to a file – gc_logs:

jcmd 9615 VM.log output=gc_logs what=gc

12. New APIs

12.1. Immutable Set

java.util.Set.of() – creates an immutable set of a given elements. In Java 8 creating a Set of several elements would require several lines of code. Now we can do it as simple as:

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

The Set returned by this method is JVM internal class: java.util.ImmutableCollections.SetN, which extends public java.util.AbstractSet. It is immutable – if we try to add or remove elements, an UnsupportedOperationException will be thrown.

You can also convert an entire array into a Set with the same method.

12.2. Optional to Stream

java.util.Optional.stream() gives us an easy way to you use the power of Streams on Optional elements:

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

13. Conclusion

Java 9 vendrá con una JVM modular y muchas otras mejoras y características nuevas y diversas.

Puede encontrar el código fuente de los ejemplos en GitHub.