JavaRush /Blog Java /Random-ES /Del 8 al 13: una descripción completa de las versiones de...

Del 8 al 13: una descripción completa de las versiones de Java. Parte 2

Publicado en el grupo Random-ES
Este artículo es la segunda parte de mi revisión de las innovaciones en las versiones 8-13 de Java. La primera parte está aquí . Sin más, pasemos al 25 de septiembre de 2018, cuando se lanzó el nuevo JDK:

Java 11

Del 8 al 13: una descripción completa de las versiones de Java.  Parte 2 - 1

var (en lambda)

De ahora en adelante, podemos especificar los tipos de parámetros lambda u omitirlos al escribir una expresión lambda (expresiones lambda escritas implícitamente):
Function<String, String> append = (var string) -> string + " Text";
String appendedString = append.apply("Some");
System.out.println(appendedString);
También puede agregar anotaciones a los parámetros lambda sin tener que escribir el nombre completo del tipo de variable:
Function<String, String> append = (@NonNull var string) -> string + " Text";

Z(ZGC)

ZGC es un nuevo recolector de basura que no funciona. Asigna nueva memoria pero nunca la reinicia. ZGC promete gestionar grandes cantidades de memoria con alto rendimiento y baja latencia (ZGC sólo está disponible en plataformas de 64 bits). Coloración de referencia: ZGC utiliza punteros de 64 bits con una técnica llamada coloración de puntero. Los punteros de colores almacenan información adicional sobre los objetos del montón. Cuando la memoria se fragmenta, esto ayuda a evitar la degradación del rendimiento cuando el GC necesita encontrar espacio para una nueva asignación. La recolección de basura mediante ZGC consta de los siguientes pasos:
  1. paradas del mundo: buscamos puntos de partida para llegar a objetos en el montón (como variables locales o campos estáticos);
  2. intersección de gráficos de objetos a partir de enlaces raíz. Marcamos cada objeto que alcanzamos (ZGC recorre el gráfico de objetos y examina los marcadores de colores, marcando los objetos disponibles);
  3. manejar algunos casos extremos, como enlaces débiles;
  4. mover objetos vivos, liberando grandes áreas del montón para acelerar la asignación.
  5. cuando comienza la fase de movimiento, ZGC divide el montón en páginas y trabaja una página a la vez;
  6. El ZGC finaliza el movimiento de las raíces y se produce el resto del movimiento.
Este tema es muy complejo y confuso. Una discusión detallada requeriría un artículo aparte, así que lo dejaré aquí:

Épsilon GC

Epsilon es un recolector de basura que maneja la asignación de memoria pero no implementa ningún mecanismo de recuperación de memoria real. Una vez que se agote el montón de Java disponible, la JVM se cerrará. Es decir, si comienzas a crear un objeto en una matriz infinita sin vincularlo a una referencia con este recolector de basura, la aplicación fallará con un OutOfMemoryError (y si con cualquier otro, no lo hará, ya que limpiará objetos sin referencias) . ¿Por qué es necesario? Este es el por qué:
  1. Pruebas de rendimiento.
  2. Pruebas de presión de memoria.
  3. Probando la interfaz de VM.
  4. Trabajo extremadamente corto.
  5. Mejoras en la latencia de última caída.
  6. Mejoras en el rendimiento de última entrega.
Enlaces útiles: Otras innovaciones:
  1. ByteArrayOutputStreamObtuve un método void writeBytes(byte [])que escribe todos los bytes del argumento en OutputStream.
  2. FileReadery FileWriterobtuve nuevos constructores que le permiten especificar Charset.
  3. Pathtomó dos métodos nuevos, of(String, String [])devuelve Pathde un argumento de cadena una ruta o secuencia de cadenas que cuando se combinan forman una cadena de ruta y of(URI): devuelve la ruta de un URI.
  4. Pattern— recibió un método asMatchPredicate()que verifica si una cadena de entrada determinada coincide con un patrón determinado (si le permite crear un predicado usando una expresión regular para que pueda, por ejemplo, filtrar datos en una secuencia).
  5. StringRecogí muchos métodos útiles, como:
    • String strip(): nos devolverá una cadena que es esta cadena, con todos los espacios al principio y al final de la cadena eliminados (similar a trim(), pero define los espacios de manera diferente);
    • String stripLeading(): nos devolverá la cadena que es esta cadena, eliminando los espacios iniciales de la cadena;
    • String stripTrailing(): nos devolverá la cadena que es esta cadena, eliminando los espacios al final de la cadena;
    • Stream lines(): nos devolverá Streamde String, extraído de esta cadena, separado por separadores de línea;
    • String repeat(int): nos devolverá una cadena que es una concatenación de esta cadena, repetida varias veces.
    • boolean isBlank(): devolverá verdadero si la cadena está vacía o contiene solo espacios; en caso contrario, devolverá falso.
  6. Thread— Se han eliminado los métodos destroy() y stop(Throwable).
  7. FilesObtuve una serie de métodos nuevos:
    • String readString(Path): lee todos los datos de un archivo en una cadena, mientras decodifica de bytes a caracteres usando codificación UTF-8;
    • String readString(Path, Charset): igual que en el método anterior, con la diferencia de que la decodificación de bytes a caracteres se produce utilizando el juego de caracteres especificado;
    • Path writeString (Path, CharSequence, OpenOption []): escribe una secuencia de caracteres en un archivo. Los caracteres se codifican en bytes mediante codificación UTF-8;
    • Path writeString(Path, CharSequence,Charset, OpenOption []): El mismo método que el anterior, solo los caracteres se codifican en bytes utilizando la codificación especificada en Charset.
Estas fueron las innovaciones API más interesantes (en mi humilde opinión), aquí hay un par de materiales para una revisión más detallada:

Java 12

Pasan seis meses y vemos la siguiente etapa en la evolución de Java. Entonces, es hora de sacar una pala de conocimiento y cavar. Del 8 al 13: una descripción completa de las versiones de Java.  Parte 2 - 2

Actualizar G1

Se han realizado las siguientes mejoras para G1:
  1. Recuperar memoria asignada no utilizada

    En la memoria dinámica de Java existe la memoria no utilizada (o en otras palabras, inactiva). En Java 12 decidieron solucionar este problema, ahora:

    • G1 devuelve memoria del montón en un GC completo o durante un bucle paralelo; G1 intenta evitar un GC completo e inicia un bucle paralelo basado en la asignación del montón. Tendremos que forzar a G1 a devolver la memoria del montón.

    Esta mejora se centra en el rendimiento al devolver automáticamente la memoria del montón al sistema operativo cuando G1 no está en uso.

  2. Abortar colecciones mixtas cuando se excede el tiempo de pausa

    G1 utiliza un motor de análisis para seleccionar la cantidad de trabajo requerido para la recolección de basura. Recopila objetos vivos sin detenerse después de definir el conjunto e iniciar la limpieza. Esto hace que el recolector de basura exceda su objetivo de tiempo de pausa. En realidad, este problema se resuelve con la mejora, ya que si el tiempo necesario para completar el siguiente paso supera los límites razonables, este paso puede interrumpirse.

Microbenchmark

Java 12 introdujo pruebas de microbenchmarking para que el rendimiento de JVM pueda probarse fácilmente utilizando los benchmarks existentes. Esto sería muy útil para cualquiera que quiera trabajar en la propia JVM. Las pruebas agregadas se crean utilizando Java Microbenchmark Harness (JMH). Estas pruebas permiten realizar pruebas continuas de rendimiento en la JVM. JEP 230 propone la introducción de aproximadamente 100 pruebas, introduciéndose nuevas pruebas a medida que se lanzan nuevas versiones de Java. A continuación se muestra un ejemplo de las pruebas que se están agregando .

Shenandoah

Este es un algoritmo de recolección de basura (GC) que tiene como objetivo garantizar tiempos de respuesta bajos (el límite inferior es de 10 a 500 ms). Esto reduce el tiempo de pausa del GC cuando se realiza el trabajo de limpieza al mismo tiempo que se ejecutan subprocesos de Java. En Shenandoah, el tiempo de pausa es independiente del tamaño del montón. Esto significa que el tiempo de pausa será el mismo independientemente del tamaño de su montón. Esta es una característica experimental y no está incluida en la versión estándar (Oracle) de OpenJDK.

Mejorar el cambio

Java 12 ha mejorado las expresiones Switch para la coincidencia de patrones. Se introdujo una nueva sintaxis L →. Aquí hay una lista de los puntos clave del nuevo cambio :
  1. La nueva sintaxis elimina la necesidad de una declaración de interrupción para evitar errores.
  2. Las expresiones de cambio ya no fallan.
  3. Además, podemos definir múltiples constantes en una sola etiqueta.
  4. Ahora se requiere el uso de mayúsculas y minúsculas por defecto en las expresiones de cambio.
  5. break se usa en expresiones Switch para devolver valores del propio registro (de hecho, un switch puede devolver valores).
Veamos esto como ejemplo:
var result = switch (someDay) {
  case "M", "W", "F" -> "MWF";
  case "T", "TH", "S" -> "TTS";
  default -> {
      if(someDay.isEmpty())
            break "Please insert a valid day.";
      else
            break "Looks like a Sunday.";
  }
};
Guía definitiva para cambiar expresiones en Java 13 Otras características nuevas:
  1. String:

    transform(Function f)- Aplica la función proporcionada a una cadena. Es posible que el resultado no sea una cadena.
    indent(int x)— agrega x espacios a la cadena. Si el parámetro es negativo, se eliminará este número de espacios iniciales (si es posible).

  2. Files- tomó un método como mismatch(), que, a su vez, busca y devuelve la posición del primer byte no coincidente en el contenido de dos archivos, o -1L si no hay discrepancias.

  3. Ha aparecido una nueva claseCompactNumberFormat para formatear un número decimal de forma compacta. Un ejemplo de esta forma compacta es 1M en lugar de 1.000.000. Por lo tanto, sólo se necesitan dos en lugar de nueve caracteres.

  4. También hay uno nuevo enum , NumberFormatStyleque tiene dos valores: LARGO y CORTO.

  5. InputStream Obtuve el método skipNBytes(long n) : omita el enésimo número de bytes del flujo de entrada.

Enlaces interesantes de Java 12:

Java 13

El mundo no se detiene, se mueve, se desarrolla, como Java - Java 13. Del 8 al 13: una descripción completa de las versiones de Java.  Parte 2 - 3

Bloque de texto

Java siempre ha sufrido un poco a la hora de definir cadenas. Si necesitábamos definir una línea con un espacio, un salto de línea, una cita o algo más, esto causaba algunas dificultades, por lo que teníamos que usar caracteres especiales: por ejemplo, \n para un salto de línea, o escapar de parte de la línea. sí mismo. Esto reduce significativamente la legibilidad del código y requiere más tiempo al escribir dicha línea. Esto se vuelve especialmente notable al escribir cadenas que muestran JSON, XML, HTML, etc. Como resultado, si queremos escribir un Json pequeño, se verá así:
String JSON_STRING = "{\r\n" + "\"name\" : \"someName\",\r\n" + "\"site\" : \"https://www.someSite.com/\"\r\n" + "}";
Y entonces entra en escena Java 13 y nos ofrece su solución en forma de comillas dobles triples antes y después del texto (a las que llamaron bloques de texto). Veamos el ejemplo json anterior usando esta innovación:
String TEXT_BLOCK_JSON = """
{
    "name" : "someName",
    "site" : "https://www.someSite.com/"
}
""";
Mucho más sencillo y claro, ¿no? También se agregaron Stringtres nuevos métodos , respectivamente, para administrar estos bloques:
  • stripIndent(): Elimina espacios aleatorios de una cadena. Esto es útil si está leyendo cadenas de varias líneas y desea aplicar el mismo tipo de exclusión de espacios en blanco aleatorios que ocurre con una declaración explícita (esencialmente simulando el compilador para eliminar espacios en blanco aleatorios);
  • formatted(Object... args ): similar a format(String format, Object... arg), pero para bloques de texto;
  • translateEscapes(): Devuelve una cadena con secuencias de escape (como \r) traducidas al valor Unicode correspondiente.

Mejorar el cambio

Las expresiones de cambio se introdujeron en Java 12 y 13 las refina. En 12 defines los valores de retorno usando break. En 13, el valor de retorno fue reemplazado por rendimiento. Ahora la expresión de cambio que teníamos en la sección Java 12 se puede reescribir como:
var result = switch (someDay) {
  case "M", "W", "F" -> "MWF";
  case "T", "TH", "S" -> "TTS";
  default -> {
      if(someDay.isEmpty())
          yield "Please insert a valid day.";
      else
          yield "Looks like a Sunday.";
  }
};
Aunque para nosotros, los programadores que ya estábamos familiarizados con Java, era normal aceptar una pausa, era bastante extraño. ¿Qué es break true tratando de decirme? La nueva palabra clave de rendimiento (relativamente nueva) es más clara y puede aparecer en otros lugares en el futuro donde se devuelven valores. Para aquellos que estén profundamente interesados ​​en este tema, les recomiendo que se familiaricen con estos materiales:

Archivos CDS dinámicos

CDS: intercambio de datos de clase. Le permite empaquetar un conjunto de clases de uso común en un archivo que luego puede ser cargado por múltiples instancias de JVM. ¿Porqué necesitamos esto? El hecho es que en el proceso de carga de clases, la JVM realiza muchas acciones que consumen muchos recursos, como leer clases, almacenarlas en estructuras internas, verificar la exactitud de las clases leídas, buscar y cargar clases dependientes, etc. ., y sólo después de todo esto las clases están listas para funcionar. Es comprensible que se desperdicien muchos recursos, ya que las instancias JVM a menudo pueden cargar las mismas clases. Por ejemplo Cadena, Lista Vinculada, Entero. Bueno, o clases de la misma aplicación, y todos estos son recursos. Si realizamos todos los pasos necesarios solo una vez y luego colocamos las clases rediseñadas en un archivo que pueda cargarse en la memoria de varias JVM, esto podría ahorrar significativamente espacio en la memoria y reducir el tiempo de inicio de la aplicación. En realidad, CDS permite crear precisamente ese tipo de archivo. Java 9 solo permitía agregar clases del sistema al archivo. Java 10: incluye clases de aplicaciones en el archivo. La creación de dicho archivo consiste en:
  • crear una lista de clases cargadas por la aplicación;
  • creando un archivo muy necesario con las clases que encontramos.
La innovación en Java 13 mejora CDS para que pueda crear un archivo cuando finaliza la aplicación. Esto significa que los dos pasos anteriores ahora se combinarán en uno. Y un punto más importante: solo se agregarán al archivo las clases que se cargaron mientras se ejecutaba la aplicación. En otras palabras, aquellas clases que todavía están contenidas en application.jar, pero que por alguna razón no se cargaron, no se agregarán al archivo.

Actualizar API de socket

La API de socket ( java.net.Socket y java.net.ServerSocket ) es esencialmente una parte integral de Java desde sus inicios, pero los sockets nunca se han actualizado en los últimos veinte años. Escritos en C y Java, eran muy, muy voluminosos y difíciles de mantener. Pero Java 13 decidió hacer sus propios ajustes en todo este asunto y reemplazó la implementación base. Ahora, en lugar de PlainSocketImpl, la interfaz del proveedor se reemplaza con NioSocketImpl . Esta nueva implementación codificada se basa en la misma infraestructura de back-end que java.nio . Esencialmente, la clase utiliza el mecanismo de bloqueo y caché del buffer java.util.concurrent (que están basados ​​en segmentos) en lugar de métodos sincronizados. Ya no requiere código nativo, lo que facilita la migración a diferentes plataformas. Aún así, tenemos una manera de volver a usar PlainSocketImpl , pero a partir de ahora NioSocketImpl se usa de forma predeterminada .

Retorno de memoria para ZGC

Como recordamos, el recolector de basura Z se introdujo en Java 11 como un mecanismo de recolección de basura de baja latencia para que la pausa del GC nunca supere los 10 ms. Pero al mismo tiempo, a diferencia de otros GC HotSpots virtuales, como Shenandoah y G1, podría devolver la memoria dinámica no utilizada al sistema operativo. Esta modificación agrega esta capacidad J a ZGC. En consecuencia, obtenemos una huella de memoria reducida junto con un rendimiento mejorado, y ZGC ahora devuelve memoria no comprometida al sistema operativo de forma predeterminada hasta que se alcanza el tamaño de almacenamiento dinámico mínimo especificado. Una cosa más: ZGC ahora tiene un tamaño de almacenamiento dinámico máximo admitido de 16 TB. Anteriormente, el límite era 4 TB. Otras innovaciones:
  1. javax.security- Se agregó una propiedad jdk.sasl.disabledMechanismspara deshabilitar los mecanismos SASL.
  2. java.nio- se ha agregado un método FileSystems.newFileSystem (Path, Map <String,?>)- respectivamente, para crear un nuevo archivo.
  3. Las clases ahora tienen métodos y java.nioabsolutos (a diferencia de relativos) . Ellos, al igual que la clase abstracta base , incluyen un método para recuperar parte del búfer.getsetBufferslice()
  4. Se agregaron javax.xml.parsersmétodos para crear instancias de fábricas DOM y SAX (con soporte de espacio de nombres).
  5. La compatibilidad con Unicode se ha actualizado a la versión 12.1.
Enlaces interesantes sobre Java 13:

Resultados

Podríamos repasar las innovaciones anunciadas en Java 14, pero dado que verá la luz muy pronto (el lanzamiento de JDK 14 está programado para el 17 de marzo de 2020), sería mejor realizar una revisión completa por separado inmediatamente después de su lanzamiento. . También me gustaría llamar su atención sobre el hecho de que en otros lenguajes de programación con largas pausas entre lanzamientos, como Python 2-3, no hay compatibilidad: es decir, si el código está escrito en Python 2, Necesito trabajar duro para traducirlo a 3. Java es especial en este sentido porque es extremadamente compatible con versiones anteriores. Esto significa que se garantiza que su programa Java 5 u 8 se ejecutará en una máquina virtual Java 8-13, con algunas excepciones de las que no necesita preocuparse por ahora. Está claro que esto no funciona al revés: por ejemplo, si su aplicación utiliza funciones de Java 13 que simplemente no están disponibles en la JVM de Java 8. Eso es todo para mí hoy, respeto a quienes han leído hasta este punto)) Del 8 al 13: una descripción completa de las versiones de Java.  Parte 2 - 5
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION