Java avanza a paso agigantado innovando constantemente después de implementar un modelo de hacer un lanzamiento cada 6 meses. El pasado 25 de septiembre de 2018 toco el turno para lanzar java 11, y con este muchas mejoras e innovaciones.

La comunidad no tardo mucho en descargarla y comenzar a revisar las nuevas características. En este post examinamos las mas importantes.

Control de acceso anidado

En las versiones anteriores de Java, por diseño podíamos anidar clases e interfaces en un mismo archivo. Estas clases e interfaces tenían acceso sin restricciones entre sus métodos y campos privados.

class Padre {
    
    class Hijo1 {
        private void haceCosas() {
            System.out.println("Hago cosas");
        }
    }

    class Hijo2 {
        private void invocarHermano() {
            Hijo1 h1 = new Hijo1();
            h1.haceCosas();
        }
    }
}

El problema que se soluciona en java 11 es que cuando queremos acceder a un método privado desde una de las clases anidadas por reflection usando java.lang.reflect.Method.invoke dará como resultado una excepción de tipo: IllegalAccessError.

Esto sucede porque antes de java 11 las reglas de la JVM no permitían acceso privado de las clases miembro. Para lograr la visibilidad entre ellas el compilador generaba un paquete automáticamente e introducía las clases privadas en el.

La solución era, naturalmente, quitar este comportamiento y codificar las reglas de la JVM para que aceptara este tipo de acceso. De este modo el trabajo del compilador se ve simplificado y mejora ligeramente el tiempo de ejecución.

Constantes Dinámicas En Archivos .class

Los archivos compilados en java contienen instrucciones especificas para la JVM. Son un conjunto de métodos y constantes que permiten enlazar todo lo que creamos para que pueda ser ejecutado.

Con la llegada de la programación funcional (lambdas) a java, fue necesario introducir una nueva constante al conjunto de constantes que maneja la JVM.

Como sabrán invokedinamic es una instrucción en bytecode que facilita la invocación de lenguajes dinámicos para la JVM, misma que actualmente tiene una colección de constantes para enlazar el código.

En el nuevo pozo de constantes CONSTANT_Dynamic cada una tiene dos componentes que le siguen a su byte de etiqueta:

  1. El indice del método de arranque
  2. El tipo esperado (CONSTANT_NameAndType)

Y conductualmente se resuelven ejecutando el método de arranque con los siguientes parámetros:

  1. Un objeto de búsqueda local
  2. La cadena que representa el componente de nombre de la constante
  3. La clase que representa el tipo de constante esperado
  4. Cualquier argumento de arranque restante

¿Qué se logra?

El método de arranque ahora soporta miles de argumentos, cosa que hasta hoy solo soportaba 251. Esto logra que se mejore la fase de enlazamiento y los errores de enlace producidos por los argumentos del método de arranque.

Mejoras En Los Arch64 Intrinsics

Los intrinsics son usados para aprovechar código ensamblador que es especifico de una arquitectura que se ejecuta en lugar de código java para un método dado, y mejorar así su desempeño.

Específicamente, se optimizaron los siguientes métodos que aun estaban pendientes para que funcionaran con intrinsics del paquete java.lang.math.

  • sin
  • cos
  • log

Epsilon: Un Garbage Collector Pasivo

Se provee un GC completamente pasivo cuya implementación tiene un limite de reserva delimitado y muy baja latencia a expensas de la huella y el rendimiento de la memoria. Una implementación exitosa que esta aislada de el resto de la JVM y de otros GCs

Epsilon es muy útil para los siguientes escenarios:

  • Pruebas de rendimiento
  • Pruebas de presión de memoria
  • Pruebas de interfaz con una VM
  • Tareas cortas (y de alto rendimiento)
  • Mejoras en la latencia
  • Mejora de rendimiento

En general, para toda tarea que necesite ser ejecutada rápida y efímeramente. Es decir: cuando no hay tiempo para limpiar la memoria porque igual  ya terminamos y el programa se cerrara en el siguiente tick del reloj.

Epsilon se usa como cualquier otro GC en la JVM y se activa con esta opción:

-XX:+UseEpsilonGC ...

Se Removieron Los Módulos Java EE y CORBA

Estos módulos fueron marcados como descontinuados en java 9 y la intención era quitarlos en las versiones futuras.

Como resultado si tu proyecto incluye alguno de los siguientes paquetes, dejará de compilar en java 11:

  • java.xml.ws (JAX-WS, y las tecnologías relacionas SAAJ y Web Services Metadada)
  • java.xml.bind (JAXB)
  • java.activation (JAF)
  • java.xml.ws.annotation (Anotaciones Comunes)
  • java.corba (CORBA)
  • java.transaction (JTA)

Y módulos de Java SE 9 que también se marcaron como obsoletos:

  • java.se.ee (Modulo agregador de los seis módulos anteriores)
  • jdk.xml.ws (Herramientas para JAX-WS)
  • jdk.xml.bind (Herramientas para JAXB)

Un Cliente HTTP Estándar

Se había comenzado a incubar un cliente http en Java 9, se hicieron algunas mejoras en Java 10 y finalmente se estandarizo en Java 11.

El nombre del modulo y paquete estándar será: java.net.http Esta implementación es completamente asíncrona a diferencia de sus versiones de incubación en java 9 y 10. Ademas de que prácticamente fue re-escrita para seguir convenciones de nombres según las especificaciones del protocolo.

Para información detallada es bueno visitar la documentación oficial:

http://cr.openjdk.java.net/~chegar/httpclient/02/javadoc/api/java.net.http/java/net/http/package-summary.html

Sintaxis De Variable Local Para Parámetros Lambda

Las expresiones lambda ahora aceptan la palabra reservada var en sus parámetros:

//antes
(x, y) -> x.metodo(y)

//ahora también
(var x, var y) -> x.metodo(y)

Como siempre en Java se busca que la sintaxis sea consistente, así que tendrás que escoger si usar var o usar el tipo explicito, ya que al combinarlos así:

(var x, int y) -> x.process(y)

Obtendrás una excepción.

Mejoras En Los Estándares Cirptografía

La demanda de usar criptografía que use las curvas elípticas Curve25519 y Curve448 se incremento debido a sus propiedades de seguridad y rendimiento. El intercambio de llaves usando estas curvas esta soportado por otras librerías como OpenSSL, BoringSSL y BouncyCastle. Y el mecanismo de intercambio es un componente opcional en TLS 1.3, y esta habilitado en versiones tempranas de TLS a través de extensiones comúnmente usadas.

Las funciones X25519 y X448 fueron implementadas según su descripción en el RFC-7748, y esas funciones fueron usadas para implementar nuevos servicios: KeyAgreement, KeyFactory y KeyPairGenerator en el proveedor existente: SunEC. La implementación usa la constante de tiempo de escalera de Montogmery descrita en el RFC-7748 para prevenir ataques de canal lateral. La implementación asegura el comportamiento de contribución comparando el resultado con O como lo describe el RFC.

Unicode 10

Java SE 10 implementa Unicode 8.0. Unicode 9.0 agrega 7,500 caracteres y seis nuevos scripts y Unicode 10.0.0 agrega 8,518 caracteres y cuatro nuevos scripts. Esta actualización incluirá los cambios en Unicode 9.0 por lo tanto se agregarán un total de 16,018 caracteres y 10 nuevos scripts.

Flight Recorder

El flight recorder provee un backend de alto rendimiento para escribir eventos en forma binaria, con el objetivo de solucionar problemas con el HotSopt JVM cuando este esta experimentando una alta carga de trabajo.

Los Módulos introducidos son:

  • jdk.jfr
    • API
    • Requiere unicamente java.base (se puede usar en dispositivos con recursos restringidos)
  • jdk.management.jfr
    • capacidades JMX
    • requiere jdk.jfr y jdk.management

Se activa con la siguiente opción:

java -XX:StartFlightRecording ...

Produciendo y consumiendo eventos

Este es un ejemplo de como producir un evento:

import jdk.jfr.*;

@Label("Evento Generico 1")
@Description("Es un evento generico para probar el registro de vuelo 8-)")
class EventoGenerico extends Event {
   @Label("Mensaje")
   String mensaje;
}

public static void main(String... args) throws IOException {
    EventoGenerico event = new EventoGenerico();
    event.mensaje = "Evento creado!!!";
    event.commit();
}

Y luego para consumirlo usamos: jdk.jfr.consumer

import java.nio.file.*;
import jdk.jfr.consumer.*;

Path p = Paths.get("recording.jfr");
for (RecordedEvent e : RecordingFile.readAllEvents(p)) {
   System.out.println(e.getStartTime() + " : " + e.getValue("mensaje"));
}

Que gran momento para estar vivo 😎

Nuevos Algoritmos Criptográficos

Se implementaron los algoritmos ChaCha20 y ChaCha20-Poly1305 como se describe en el RFC-7539. ChaCha20 es un relativamente nuevo cifrado para transmisión que reemplaza al viejo e inseguro RC4.

La inicialización de ChaCha20 aceptara una nueva implementación de AlgorithmParameterSpec segun javax.crypto.spec.ChaCha20ParameterSpec:

ChaCha20ParameterSpec(byte[] nonce, int counter);     // Constructor
public byte[] getNonce();     // obtiene una copia del nonce
public int getCounter();     // obtiene una copia del valor inicial del contador

Y el nonce tiene que tener exactamente 96 bits. cualquier otro valor hace que se arroje una excepción.

De modo que si queremos encriptar algo usando ChaCha20, podemos hacer lo siguiente:

Cipher mambo = Cipher.getInstance("ChaCha20");
ChaCha20ParameterSpec mamboSpec = new ChaCha20ParameterSpec(nonceBytes, 7);   // Usamos un valor inicial del contador de "7"
// Encriptamos!
mambo.init(Cipher.ENCRYPT_MODE, key, mamboSpec);
byte[] encryptedResult = mambo.doFinal(texto);

Y similarmente para ChaCha20-Poly1305

Cipher mambo = Cipher.getInstance("ChaCha20-Poly1305");
AlgorithmParameterSpec mamboSpec = new IvParameterSpec(nonceBytes);

// Encriptamos!
mambo.init(Cipher.ENCRYPT_MODE, key, mamboSpec);
byte[] resultado = new byte[mambo.getOutputSize(texto.length)];
mambo.doFinal(texto, 0, texto.length, resultado);

Programas de un solo archivo

Esta característica me entristece mas de lo que me emociona, ya que siento que quieren, lentamente, convertir a Java en un lenguaje de scripting. Por el lado amable, Java sera un lenguaje de scripting (orientado a objetos) Y un lenguaje orientado a objetos formal, interpretado.

Según la nota oficial el objetivo es hacer que aprender java sea mas fácil (para los millennials)

Esencialmente pueden poner código en un archivo java y ejecutarlo como si fuera su hermano con menos features javascript:

java HolaMundo.java

¿Le quieres pasar argumentos?… claro que se puede!

java Factorial.java 3 4 5

Y se escanean las siguientes opciones para operar el archivo:

  • –class-path
  • –module-path
  • –add-exports
  • –add-modules
  • –limit-modules
  • –patch-module
  • –upgrade-module-path

Porque aparentemente es importante para los millennials que sea fácil introducir anti-patrones y hacer cosas que no son mantenibles 😉

Perfil De Pila De Baja Sobrecarga

La API del usuario consiste en una extensión a la interfaz de herramientas de la JVM (JMVTI) que permite perfilar el tamaño la cola de memoria.

Los sistemas siguientes dependen de una notificación de un evento que proveerá un callback como:

void JNICALL
SampledObjectAlloc(jvmtiEnv *jvmti_env,
    JNIEnv* jni_env,
    jthread thread,
    jobject object,
    jclass object_klass,
    jlong size)

donde:

  • thread es el trhead que reserva el jobject
  • object es la referencia al jobject que se esta muestreando
  • object_klass es la clase para el jobject
  • size es el tamaño de la reserva

La nueva API también incluye un nuevo método en el JVMTI

jvmtiError  SetHeapSamplingInterval(jvmtiEnv* env, jint sampling_interval)

Donde sampling_interval es el promedio reservado de bytes entre cada muestra. La especificación del método es:

  • Si no es cero, el intervalo de muestra es actualizado y enviara un callback al usuario con el nuevo promedio del intervalo de muestra en bytes de sampling_interval
  • Si es cero, el método de muestreo, revisa cada reserva una vez que el nuevo intervalo es tomado en cuenta, lo cual puede haber tomado cierto numero de reservas

TLS 1.3

TLS 1.3 es una nueva versión de TLS la cual supercede y descontinúa versiones previas de TLS incluyendo la 1.2 (RFC-5246). Cambien descontinúa o cambia otras características como las exenciones OCSP (RFC-6066, RFC-6961), y el hash de sesión y la extensión extended master secret (RFC-7627)

ZGC: Un Garbage Collector Escalable De Baja Latencia

 

ZGC es un compacting collector de generación única, basado en la región, consciente de NUMA. Las fases en las que este GC pausa no incrementan el tamaño de la cola de memoria.

Un principio general de ZGC es el uso de barreras de carga en combinación con punteros de objetos de colores. Esto es lo que habilita a ZGC a hacer operaciones concurrentes. como la re-ubicación de objetos mientras la aplicación sigue corriendo. Desde la perspectiva de un hilo de Java, el acto de cargar un campo de referencia esta sujeto a una barrera de carga. Adicionalmente a una dirección a un objeto, un objeto con color contiene información usada por la barrera de carga para determinar si se necesita efectuar alguna accion antes de permitir que el hilo use determinado puntero. Por ejemplo: un objeto podria haber sido reubicado, en caso de que la barrera de carga detecte que la situación lo amerita.

Para habilitarlo se necesitan las siguientes opciones de la JVM:

-XX:+UnlockExperimentalVMOptions -XX:+UseZGC ...

JavaScript Nashorn Descontinuado

Los siguientes paquetes fueron descontinuados, de usarlos, los desarrolladores deberán buscar alternativas ya que serán removidos definitivamente en las siguientes versiones:

  • dk.scripting.nashorn — contiene jdk.nashorn.api.scripting y jdk.nashorn.api.tree
  • jdk.scripting.nashorn.shell — contiene la herramienta jjs. Correr jjs mostrara la siguiente advertencia:
Warning: The jjs tool is planned to be removed from a future JDK release.

Pack200 Tools y API Descontinuados

Los siguientes paquetes fueron descontinuados, de usarlos, los desarrolladores deberán buscar alternativas ya que serán removidos definitivamente en las siguientes versiones:

  • java.util.jar.Pack200
  • java.util.jar.Pack200.Packer
  • java.util.jar.Pack200.Unpacker

Categorized in:

Tagged in:

, , ,