Java 10 es la versión más rápida de Java en sus 23 años de historia. Java ha sido criticado por su crecimiento lento y evolución, pero Java 10 acaba de romper ese concepto. Java 10 es una versión con muchos cambios futuristas, cuyo alcance e impacto pueden no ser obvios pero son de gran alcance. En este artículo, discutiremos las diversas características agregadas en la versión 10 de Java. Antes de eso, repasemos algunos cambios introducidos en el modelo de lanzamiento de Java.
Modelo de Soporte a Largo Plazo
A partir de 2017, Oracle y la comunidad de Java anunciaron su cambio a un nuevo ritmo de 6 meses para Java. Se trasladó a un modelo de Soporte a Largo Plazo (LTS) para los productos Oracle Java SE. ¿Qué significa esto? La versión LTS de los productos ofrecerá soporte premier y sostenido por parte de Oracle y se dirigirá cada 3 años. Cada lanzamiento de Java se modela según una o dos características principales; estas características impulsan el lanzamiento. Cualquier obstáculo pospone el lanzamiento y llega tarde al mercado. Project Jigsaw fue una característica importante de Java 9, retrasó las fechas de lanzamiento varias veces y el lanzamiento se demoró más de 1.5 años. El lanzamiento cada 6 meses seguirá un “release train”. El “release train” tendrá un calendario cada 6 meses. Las características que cumplen con los requisitos se incorporan al tren; de lo contrario, esperan al próximo tren programado.
Oracle JDK vs Open JDK
Para ser más amigable para los desarrolladores, la comunidad de Oracle y Java ahora promueve las binarias de OpenJDK como el JDK principal en adelante. Esto es un gran alivio de los días anteriores, donde las binarias del JDK eran de propiedad y con licencia de Oracle, lo que tenía varias restricciones en torno a la redistribución. Oracle, sin embargo, seguirá produciendo su JDK, pero solo para versiones de soporte a largo plazo. Este es un paso hacia ser más amigable con la nube y los contenedores, ya que las binarias de OpenJDK pueden distribuirse como parte de un contenedor. ¿Qué significa esto? Las binarias de OpenJDK se lanzarán cada 6 meses, mientras que las binarias de Oracle JDK se lanzarán cada 3 años (versión LTS). ¿Qué binarias de JDK serán adoptadas? Las grandes organizaciones tardan en cambiar entre las versiones; se aferran a la versión hasta que pueden. La adopción de la industria para Java 6 fue más que Java 7 y luego la industria se está moviendo gradualmente a Java 8. En mi opinión, las versiones LTS serán las más favorecidas por las empresas. Sin embargo, si serán la versión LTS de Oracle JDK o la de OpenJDK aún está por verse, en parte porque hay mucho en el espacio de la nube. Java 9 y 10 son versiones no LTS. Java 11, que está previsto para septiembre de 2018, será una versión LTS.
Características de Java 10
Echemos un vistazo a las características disponibles en Java 10.
Con la adopción del ciclo de lanzamiento basado en el tiempo, Oracle cambió el esquema de cadenas de versión de la Plataforma Java SE y el JDK, así como la información de versiones relacionada, para los modelos de lanzamiento basados en el tiempo presentes y futuros. El nuevo patrón del número de versión es: $$FEATURE.$INTERIM.$UPDATE.$PATCH$$ $FEATURE: el contador se incrementará cada 6 meses y se basará en las versiones de lanzamiento de funciones, por ejemplo: JDK 10, JDK 11. $INTERIM: el contador se incrementará para lanzamientos no relacionados con funciones que contengan correcciones de errores compatibles y mejoras, pero sin cambios incompatibles. Por lo general, esto será cero, ya que no habrá lanzamientos intermedios en un período de seis meses. Esto se mantiene para una revisión futura del modelo de lanzamiento. $UPDATE: el contador se incrementará para lanzamientos de actualización compatibles que solucionen problemas de seguridad, regresiones y errores en funciones más nuevas. Esto se actualiza un mes después del lanzamiento de la función y cada 3 meses después. El lanzamiento de abril de 2018 es JDK 10.0.1, el lanzamiento de julio es JDK 10.0.2, y así sucesivamente. $PATCH: el contador se incrementará para un lanzamiento de emergencia para solucionar un problema crítico. Se han agregado nuevas API para obtener estos valores de contador programáticamente. Echemos un vistazo;
Version version = Runtime.version();
version.feature();
version.interim();
version.update();
version.patch();
Ahora, echemos un vistazo al lanzador de Java que devuelve la información de la versión:
$ java -version
java version "10" 2018-03-20
Java(TM) SE Runtime Environment 18.3 (build 10+46)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10+46, mixed mode)
El formato del número de versión es “10” ya que no hay otro contador que no sea cero. Se agrega la fecha de lanzamiento. 18.3 se puede leer como el Año 2018 y el 3er Mes, el compilado 10+46 es el 46º compilado para la versión 10. Para un compilado hipotético 93 de JDK 10.0.1, el compilado será 10.0.1+939. ### Inferencia de Tipo de Variable Local (JEP 286)
La inferencia de tipo de variable local es la mayor característica nueva en Java 10 para desarrolladores. Agrega inferencia de tipo a las declaraciones de variables locales con inicializadores. La inferencia de tipo local solo se puede usar en los siguientes escenarios:
- Limitado solo a variable local con inicializador
- Índices del bucle for mejorado o índices
- Local declarado en bucle for
Vamos a echar un vistazo a su uso:
var numbers = List.of(1, 2, 3, 4, 5); // inferred value ArrayList
// Índice del bucle for mejorado
for (var number : numbers) {
System.out.println(number);
}
// Variable local declarada en un bucle
for (var i = 0; i < numbers.size(); i++) {
System.out.println(numbers.get(i));
}
Puedes leer más al respecto en nuestra publicación exclusiva sobre inferencia de tipo de variable local en Java 10.
Esta característica permite que el compilador JIT basado en Java, Graal, se utilice como un compilador JIT experimental en la plataforma Linux/x64. Esta es, con mucho, la inclusión más futurista en la lista de características de Java 10. Graal fue introducido en Java 9. Es una alternativa al compilador JIT al que estábamos acostumbrados. Es un complemento para la JVM, lo que significa que el compilador JIT no está vinculado a la JVM y se puede conectar dinámicamente y reemplazar con cualquier otro complemento que cumpla con JVMCI (Interfaz de Compilador de JVM a Nivel de Java). También introduce la compilación Ahead of Time (AOT) en el mundo de Java. También admite la interpretación de lenguajes políglotas. “Un compilador Just in Time basado en Java escrito en Java para convertir el bytecode de Java en código máquina”. ¿Es confuso? Si JVM está escrita en Java, ¿no necesitas una JVM para ejecutar la JVM? La JVM se puede compilar AOT y luego el compilador JIT se puede usar dentro de la JVM para mejorar el rendimiento mediante la optimización de código en vivo. Graal es una reescritura completa del compilador JIT en Java desde cero. El compilador JIT anterior estaba escrito en c++. Se considera uno de los últimos estados de evolución para cualquier lenguaje de programación. Puedes cambiar a Graal con los siguientes parámetros de JVM:
-XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler
Puedes obtener más información sobre Graal en la presentación de Chris Seaton.
Esta característica ayuda a mejorar la huella de inicio de la startup, extiende la característica existente de Compartir Datos de Clase (“CDS”) para permitir que las clases de la aplicación se coloquen en el archivo compartido. JVM al iniciar realiza algunos pasos preliminares, uno de los cuales es cargar las clases en memoria. Si hay varios archivos JAR con múltiples clases, entonces el retraso en la primera solicitud es claramente visible. Esto se convierte en un problema con la arquitectura sin servidor, donde el tiempo de arranque es crítico. Para reducir el tiempo de inicio de la aplicación, se puede utilizar la compartición de datos de clase de aplicación. La idea es reducir la huella compartiendo metadatos de clase comunes entre diferentes procesos Java. Esto se puede lograr mediante los siguientes 3 pasos: Determinación de las clases a archivar: Utilice el lanzador de Java para crear una lista de archivos para archivar, esto se puede lograr mediante los siguientes parámetros:
$java -Xshare:off -XX:+UseAppCDS -XX:DumpLoadedClassList=hello.lst -cp hello.jar HelloWorld
Creación del archivo AppCDS: Utilice el lanzador de Java para crear el archivo de la lista de archivos que se utilizarán para la CDS de la aplicación, esto se puede lograr mediante los siguientes parámetros:
$java -Xshare:dump -XX:+UseAppCDS -XX:SharedClassListFile=hello.lst -XX:SharedArchiveFile=hello.jsa -cp hello.jar
Uso del archivo AppCDS: Utilice el lanzador de Java con los siguientes parámetros para utilizar la CDS de la aplicación.
$java -Xshare:on -XX:+UseAppCDS -XX:SharedArchiveFile=hello.jsa -cp hello.jar HelloWorld
G1 El recolector de basura se convirtió en el predeterminado en JDK 9. El recolector de basura G1 evita cualquier recolección de basura completa, pero cuando los hilos concurrentes para la recolección no pueden revivir la memoria lo suficientemente rápido, la experiencia de los usuarios se ve afectada. Este cambio mejora la latencia en el peor de los casos de G1 al hacer que la recolección completa sea paralela. El algoritmo de marca-barrido-compacción del recolector G1 se paraleliza como parte de este cambio y se activará cuando los hilos concurrentes para la recolección no puedan revivir la memoria lo suficientemente rápido.25. ### Interfaz del Recolector de Basura (JEP 304)
Este JEP es un cambio futurista. Mejora el aislamiento de código de diferentes recolectores de basura al introducir una Interfaz Común de Recolector de Basura. Este cambio proporciona una mejor modularidad al Código Interno del Recolector de Basura. Ayudará en el futuro a agregar nuevos recolectores de basura sin cambiar la base de código existente, también ayudará a eliminar o limpiar los recolectores de basura anteriores.26. ### Extensiones adicionales de etiquetas de idioma Unicode (JEP 314)
Esta característica mejora java.util.Locale y APIs relacionadas para implementar extensiones adicionales de Unicode de etiquetas de idioma BCP 47. A partir de Java SE 9, las extensiones de etiqueta de idioma BCP 47 U compatibles son “ca” y “nu”. Este JEP agregará soporte para las siguientes extensiones adicionales:
- cu (tipo de moneda)
- fw (primer día de la semana)
- rg (anulación de región)
- tz (zona horaria)
Para poder admitir estas extensiones adicionales, se realizan cambios en varias API para proporcionar información basada en U o extensiones adicionales.
java.text.DateFormat::get*Instance
java.text.DateFormatSymbols::getInstance
java.text.DecimalFormatSymbols::getInstance
java.text.NumberFormat::get*Instance
java.time.format.DateTimeFormatter::localizedBy
java.time.format.DateTimeFormatterBuilder::getLocalizedDateTimePattern
java.time.format.DecimalStyle::of
java.time.temporal.WeekFields::of
java.util.Calendar::{getFirstDayOfWeek,getMinimalDaysInWeek}
java.util.Currency::getInstance
java.util.Locale::getDisplayName
java.util.spi.LocaleNameProvider
Con el fin de promover OpenJDK y hacerlo más atractivo para los usuarios de la comunidad, esta característica proporciona un conjunto predeterminado de certificados de Autoridad de Certificación (CA) raíz en el JDK. Esto también significa que los binarios tanto de Oracle como de OpenJDK serán funcionalmente iguales. Los componentes de seguridad críticos como TLS funcionarán de forma predeterminada en las compilaciones de OpenJDK en adelante.30. ### Handshakes Thread-Local (JEP 312)
Esta es una característica interna de la JVM para mejorar el rendimiento. Una operación de handshakes es una devolución de llamada que se ejecuta para cada JavaThread mientras ese hilo está en un estado de safepoint. La devolución de llamada se ejecuta ya sea por el hilo mismo o por el hilo de la VM mientras mantiene el hilo en un estado bloqueado. Esta característica proporciona una forma de ejecutar una devolución de llamada en hilos sin realizar un safepoint global de la VM. Hace posible y económico detener hilos individuales y no solo todos los hilos o ninguno.31. ### Asignación de montón en dispositivos de memoria alternativos (JEP 316)
Las aplicaciones se han vuelto exigentes en memoria; hay un aumento en las aplicaciones nativas de la nube, bases de datos en memoria y aplicaciones de transmisión. Para atender a estos servicios, existen diversas arquitecturas de memoria disponibles. Esta característica mejora la capacidad de HotSpot VM para asignar el montón de objetos Java en un dispositivo de memoria alternativo, como un NV-DIMM, especificado por el usuario. Este JEP se enfoca en dispositivos de memoria alternativos que tienen las mismas semánticas que la DRAM, incluidas las semánticas de operaciones atómicas, y, por lo tanto, pueden utilizarse en lugar de la DRAM para el montón de objetos sin ningún cambio en el código de la aplicación existente.32. ### Eliminar la herramienta de generación de encabezados nativos – javah (JEP 313)
Este es un cambio de mantenimiento para eliminar la herramienta javah del JDK. La funcionalidad de la herramienta se agregó en javac
como parte de JDK 8, lo que proporciona la capacidad de escribir archivos de encabezado nativos en tiempo de compilación, haciendo que javah
sea inútil.35. ### Consolidar el bosque JDK en un solo repositorio (JEP 296)
A lo largo de los años, ha habido varios repositorios de Mercurial para el código fuente de JDK. Si bien diferentes repositorios ofrecen algunas ventajas, también tenían diversos inconvenientes operativos. Como parte de este cambio, se combinan numerosos repositorios del bosque JDK en un solo repositorio para simplificar y optimizar el desarrollo.36. ### Cambios en la API
Java 10 ha añadido y eliminado (Sí, no es un error tipográfico) API’s. Java 9 introdujo la depreciación mejorada donde ciertas API’s fueron marcadas para ser eliminadas en futuras versiones. API’s Eliminadas: Puedes encontrar las API’s eliminadas aquí. API’s Añadidas: Se añadieron 73 nuevas API’s en Java 10. Puedes encontrar las API’s añadidas junto con la comparación aquí. Vamos a revisar algunas adiciones:
- Se han añadido las interfaces List, Map y Set con un método estático copyOf(Collection). Devuelve una List, Map o Set inmodificable que contiene las entradas proporcionadas. Para una List, si la List dada se modifica posteriormente, la List devuelta no reflejará dichas modificaciones.
- Optional y sus variaciones primitivas obtienen un método orElseThrow(). Es exactamente lo mismo que get(), sin embargo, la documentación de Java indica que es una alternativa preferida a get()
- La clase Collectors obtiene varios métodos para la recopilación de colecciones inmodificables (Set, List, Map)
List actors = new ArrayList<>();
actors.add("Jack Nicholson");
actors.add("Marlon Brando");
System.out.println(actors); // prints [Jack Nicholson, Marlon Brando]
// Nueva API añadida - Crea una List inmodificable a partir de una List.
List copyOfActors = List.copyOf(actors);
System.out.println(copyOfActors); // prints [Jack Nicholson, Marlon Brando]
// copyOfActors.add("Robert De Niro"); Generará una
// UnsupportedOperationException
actors.add("Robert De Niro");
System.out.println(actors);// prints [Jack Nicholson, Marlon Brando, Robert De Niro]
System.out.println(copyOfActors); // prints [Jack Nicholson, Marlon Brando]
String str = "";
Optional name = Optional.ofNullable(str);
// Nueva API añadida - es la opción preferida frente al método get()
name.orElseThrow(); // same as name.get()
// Nueva API añadida - Collectors.toUnmodifiableList
List collect = actors.stream().collect(Collectors.toUnmodifiableList());
// collect.add("Tom Hanks"); // Generará una
// UnsupportedOperationException
Conclusión
En este artículo, repasamos las diferentes adiciones de nuevas características de Java 10. Si crees que se pasó por alto algo importante aquí, por favor avísanos a través de los comentarios. Como de costumbre, puedes revisar el código completo en GitHub aquí.
Source:
https://www.digitalocean.com/community/tutorials/java-10-features