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.