La versión Long-Term-Support (LTS) del lenguaje Java y la plataforma de tiempo de ejecución Java 17 se lanzó el 14 de septiembre de 2021. Conozcamos las novedades de Java 17 y si debería actualizarse.

Muchas aplicaciones utilizan versiones antiguas de Java, incluidas las versiones LTS anteriores de Java: Java 11 y Java 8.

¿Por qué deberían las empresas actualizarse a la versión más actual de Java? La actualización a Java 17 requiere un esfuerzo, principalmente para aprovechar al máximo las nuevas características y funciones dentro de la JVM.

Muchas empresas utilizan Docker y las imágenes Docker para cambiar a Java 17 fácilmente con el mínimo esfuerzo y tiempo. Los desarrolladores pueden definir sus pipelines de integración/despliegue continuos (CI/CD) y ejecutar todo en imágenes Docker. Esto no afectará a otros equipos que utilicen versiones anteriores de Java, ya que pueden utilizar imágenes Docker antiguas.

Características de JAVA 17

compatibilidad con macOS y AArch64

Una de las características críticas de JVM añadidas a esta versión es la mejora del soporte para macOS en arquitectura AArch64 utilizando JEP 391. Dará soporte a la última serie de procesadores (M1) que Apple lanzó con sus ordenadores en el último año.

No es necesariamente un gran problema para los usuarios de esas plataformas, ya que algunos proveedores han lanzado versiones de JDK que soportan esta arquitectura e incluso devuelven el soporte a partir de Java 8. Sin embargo, el sello oficial de aprobación es esencial para garantizar el futuro mantenimiento y soporte de la plataforma. En comparación, el soporte para la plataforma Linux/AArch64 se ha añadido a Java 9 y Windows/AArch64 en Java 16.

Clases selladas

Clases selladas es una característica que se introdujo en Java 17. La característica de Clases selladas ha finalizado su fase de prueba y se ha convertido en una plataforma y un lenguaje oficiales en Java 17. Permite a un desarrollador especificar los subtipos permitidos que puede tener un tipo e impedir que otros lo amplíen o implementen de una forma no prevista.

Las clases selladas también permiten al compilador generar errores en tiempo de compilación cuando se intenta convertir un tipo no sellado en un subtipo no permitido. Java 17 también trae una nueva canalización de renderizado para las aplicaciones AWT/Swing que se ejecutan en macOS utilizando la API Metal de Apple en lugar de OpenGL. Dispone de una API mejorada y de funciones mejoradas para generar números aleatorios.

Cambios, supresiones y limitaciones en Java 17

Java 17 también trae consigo varios cambios, supresiones y nuevas limitaciones.

Encapsulación de las funciones internas del JDK

Un cambio es la conclusión del proceso de encapsulación de los JDK Internals. La primera vez que se introdujo esto fue en Java 9 y daba advertencias durante el tiempo de ejecución cuando un usuario intentaba utilizar la reflexión o algo similar para eludir las restricciones habituales sobre el uso de API internas. También se añadieron argumentos de línea de comandos para regular este comportamiento.

A partir de Java 9, se crearon varias API para ofrecer una forma uniforme de realizar las tareas más utilizadas; los usuarios utilizarían estas API de forma interna. Con Java 16, se pasó de una advertencia a deshabilitar el acceso lanzando una excepción. Sin embargo, utiliza el argumento de línea de comandos para alterar el comportamiento.

Con Java 17, se elimina el argumento de la línea de comandos y es posible desactivar esta restricción. Esto significa que todo acceso no autorizado a esas API internas está ahora protegido.

Semántica de punto flotante siempre estricta

Una «eliminación» adicional puede describirse como la reintroducción de la semántica de punto flotante siempre estricta. Java 1.2 introdujo modificaciones en la semántica de punto flotante por defecto en Java que permite a la JVM intercambiar una pequeña cantidad de precisión en los cálculos de punto flotante para mejorar el rendimiento. En las clases y métodos en los que debía utilizarse una semántica estricta, se añadió la palabra clave strictfp. Desde entonces, se han introducido en las CPU varios tipos de conjuntos de instrucciones que hacen que la semántica estricta de coma flotante pueda utilizarse sin costes innecesarios. Se ha eliminado la necesidad de implementar una semántica estricta o por defecto.

Java 17 elimina la anterior semántica por defecto, y todas las operaciones en coma flotante se ejecutan de forma estricta. El término strictfpsigue presente. Sin embargo, no tiene ningún efecto y provoca una advertencia en tiempo de compilación.

Compilación Ahead-of-Time (AOT)

Java 9 introdujo la compilación ahead-of-time (AOT) como una característica experimental que utiliza el compilador Graal, y se escribió un código JIT utilizando Java. Java 10 hizo que el compilador Graal pudiera utilizarse como compilador JIT en OpenJDK al incorporar la interfaz JVMCI. Desde su lanzamiento, se ha producido una gran mejora. El compilador Graal ha experimentado enormes avances y tiene su JVM bajo el nombre de GraalVM.

Activación de RMI

La activación RMI se eliminó en JEP 407 tras su eliminación en Java 8 y finalmente quedó obsoleta y marcada como requisito para su eliminación en Java 15. La Activación RMI proporcionaba un método para habilitar recursos bajo demanda de objetos distribuidos utilizando RMI. Sin embargo, su uso fue mínimo y en la actualidad existe una alternativa mejor. El resto de RMI no se ve afectado por la eliminación de la parte de Activación.

Eliminación de la API Applet

La API Applet ha sido finalmente designada para su eliminación por JEP 398, inicialmente eliminada en Java 9. La API Applet proporcionaba una forma de integrar controles Java AWT/Swing en una página web dentro de un navegador. Sin embargo, ningún navegador moderno puede soportar esto, lo que significa que los Applets han sido esencialmente inaccesibles durante la última década más o menos.

Gestor de seguridad

La deprecación más crucial es la del gestor de seguridad ( JEP 411). El gestor de seguridad ha estado en uso durante un tiempo desde Java 1.0. Fue diseñado para restringir lo que Java podía hacer localmente en la máquina, como limitar el acceso a redes, archivos y otros recursos de red. También intenta hacer un sandbox del código que no es de confianza bloqueando la reflexión y APIs específicas.

El fin del Gestor de Seguridad comenzó en Java 12. Se añadió un argumento de línea de comandos para bloquear el uso del gestor de seguridad en tiempo de ejecución. El cambio realizado en Java 17 significa que se generará una advertencia en tiempo de ejecución en la JVM cuando se intente establecer un gestor de seguridad, ya sea desde la línea de comandos o dinámicamente en tiempo de ejecución.

Características de la incubadora y la vista previa

Muchos se preguntaban si Java 17 tendría alguna característica de vista previa e incubadora, teniendo en cuenta que Java 17 se promocionó como una versión soportada a largo plazo. ¡Java 17 tiene dos módulos de incubadora y una función de vista previa!

API vectorial

Vector API ( JEP 414) se encuentra actualmente en su segunda fase de la incubadora. La API permite a los desarrolladores definir un cálculo vectorial que el compilador JIT convertirá después en la instrucción vectorial adecuada soportada por la arquitectura de CPU en la que se ejecute la JVM (por ejemplo, utilizando las de los conjuntos de instrucciones SSE o AVX).

Antes, los desarrolladores tenían que utilizar funciones escalares o crear bibliotecas nativas específicas de la plataforma. La implementación de la API vectorial en Java también proporciona un mecanismo de retroceso sin fisuras que resultaba complicado en versiones anteriores.

La estandarización de la API de vectores permite que las clases del JDK puedan utilizarla. Los métodos Arrays mismatch() de Java podrían modificarse para ejecutarse en Java en su lugar, eliminando el requisito de mantener y escribir múltiples implementaciones específicas de la plataforma dentro de la JVM.

API de funciones y memoria externas

Una característica adicional de la incubadora se denomina API de Función y Memoria Extrañas ( JEP 412). Es una evolución y fusión de otros dos módulos incubadores de Java 16 que son The Foreign Linker API ( JEP 389) y Foreign-Memory API ( JEP 393). Ambos proporcionan acceso a la memoria nativa y al código mediante programación de tipado estático escrita en Java.

Coincidencia de patrones para Switch

La última característica de la vista previa del lenguaje incluida en Java 17 es la inclusión de Pattern Matching for Switch ( JEP 406). Esta característica del lenguaje amplía las expresiones y sentencias switch según el tipo, de forma similar a la sintaxis utilizada a través de Pattern Matching(JEP 394), que se convirtió en estándar con Java 16.

En el pasado, si deseaba realizar diferentes acciones en función de la naturaleza dinámica de un objeto, debía construir una cadena if-else utilizando una instancia de comprobación del tipo

String tipo(Objeto o) {
  if (o instanceof Lista) {
    return "Una Lista de cosas";
  }
  else if (o instanceof Map) {
    return "¡Un Mapa! Tiene claves y valores";
  }
  else if (o instanceof String) {
    return "Es una cadena";
  }
  else {
    return "Esto es otra cosa";
  }
}

Combinando la expresión switch así como la nueva función de concordancia de patrones para switches, el proceso puede reducirse a algo similar a

String tipo(Objeto o) {
  return switch (o) {
    case Lista l -> "Una Lista de cosas";
    case Mapa m -> "¡Un Mapa! Tiene claves y valores";
    case String s -> "Esto es una cadena";
    default -> "Esto es otra cosa";
  };
}

Como habrá notado, hay una declaración de una variable en el proceso de comprobación. Al igual que las otras variables en Pattern, la coincidencia de instancia indica que este objeto fue comprobado en tipo y cast y está disponible en la variable dentro de su área actual.

La función de vista previa es otro paso hacia la concordancia de patrones. El siguiente paso es incluir la capacidad de deconstruir matrices y registros.

¿Debería actualizarse a Java 17?

Sí, debe actualizarse constantemente a la versión más reciente, aunque no tan pronto como el primer día. Es posible que el software y las bibliotecas que esté utilizando no se hayan actualizado para incluir la compatibilidad con Java 17, por lo que es posible que tenga que esperar algún tiempo hasta que se haga.

Si está atascado con una versión LTS de Java como Java 8 o Java 11, hay numerosas opciones dentro del lenguaje y dentro de la propia JVM que requieren una actualización hasta Java 17. Al tratarse de una versión de mantenimiento a largo plazo, existe una alta probabilidad de que su entorno de producción también se actualice finalmente a Java 17.

Si está comenzando un proyecto completamente nuevo, o está en proceso de preparar su proyecto y prepararlo para Java 17, hacer el cambio a Java 17 más pronto que tarde es probablemente la opción más eficiente, ya que reduce los costes de la mudanza. Esto también permite a los desarrolladores que trabajan en el proyecto utilizar todas las últimas características y la parte de operaciones.

Podrá aprovechar las numerosas mejoras que se han producido en los últimos años, como la compatibilidad mejorada con los contenedores que se ejecutan en Java, así como las nuevas implementaciones de recolectores de basura de baja latencia.