JDK 28 quiere que dejes de ajustar -Xmx con ZGC
Los JEP 545 y 546 ya están asignados a JDK 28. ZGC arrancará con un heap de 2 MB, crecerá de forma agresiva y, si activas el dimensionado adaptativo, decidirá solo cuánta memoria usa. En el caso de estudio con Spring PetClinic, el calentamiento baja de 80 a 10 segundos.
Si usas ZGC, seguro que tienes un -Xms y un -Xmx en el script de arranque que alguien ajustó a ojo hace tiempo. JDK 28 viene a decirte que sobran. Los JEP 545 y 546 acaban de pasar a Targeted para JDK 28 y, juntos, cambian cómo ZGC consigue memoria y cómo la devuelve.
El dilema que quieren quitarte
Con ZGC, pedir memoria al sistema operativo y prepararla como heap es caro, y el -Xms te obligaba a elegir:
- Heap inicial pequeño: arranque rápido y calentamiento lento, porque ZGC tiene que ir comprometiendo memoria mientras la aplicación crea objetos.
- Heap inicial grande: calentamiento rápido y arranque lento.
El JEP 545 pone cifras: en hardware actual, la JVM con ZGC arranca en una décima de segundo con un heap inicial de 2 MB y tarda más de diez segundos con 32 GB. Y -XX:+AlwaysPreTouch, el truco de siempre para calentar antes, empeora todavía más el arranque.
JEP 545: arrancar con poco y crecer rápido
- El heap inicial por defecto pasa a 2 MB, lo justo para una región. Hasta ahora ZGC comprometía 1/64 de la memoria física, es decir, 2 GB en una máquina de 128 GB.
- Expansión agresiva. En cuanto detecta ciclos de GC frecuentes, ZGC estima el ritmo de asignación y amplía el heap en saltos cada vez mayores. Lo hace con sus propios hilos de trabajo, que nunca pasan del 25 % de los hilos de CPU disponibles, para que la espera al sistema operativo no la paguen tus hilos.
- Pre-touch concurrente. Esos mismos hilos escriben en las páginas recién comprometidas, así que tu aplicación no se come los fallos de página durante el calentamiento.
- Páginas grandes en Linux. Desde Linux 6.1, cualquier proceso puede pedir que un rango de páginas pequeñas pase a páginas grandes sin configurar el kernel, y ZGC lo aprovechará al expandir el heap. El JEP no promete lo mismo en todos los sistemas: en Windows, por ejemplo, puede que no se usen.
- La memoria se gestiona en unidades de 2 MB en lugar de 4 KB.
JEP 546: que ZGC decida el tamaño
El dimensionado adaptativo es opcional: se activa con -XX:+ZAdaptiveHeapSizing. A partir de ahí:
- El máximo por defecto pasa del 25 % de la memoria física al 100 %, menos una pequeña reserva.
- Al final de cada ciclo, el heap crece o encoge para mantener el uso de CPU del GC cerca de un objetivo.
- Reacciona a la presión de memoria y CPU del host. Una JVM que usa mucha memoria y poca CPU encoge, y una que va justa de CPU crece; varias JVM en la misma máquina acaban repartiéndose los recursos.
El único mando nuevo es -XX:ZGCIntensity, un entero positivo que vale 5 por defecto. Más bajo, menos CPU y más memoria; más alto, al revés. El JEP avisa de que la relación exacta con el consumo de CPU no está especificada y puede cambiar.
# JDK 28: eliges ZGC y dejas que dimensione el heap
java -XX:+UseZGC -XX:+ZAdaptiveHeapSizing -jar app.jar
# Un poco menos de CPU a cambio de algo más de memoria
java -XX:+UseZGC -XX:+ZAdaptiveHeapSizing -XX:ZGCIntensity=4 -jar app.jarLas opciones de siempre, -Xmx y -XX:SoftMaxHeapSize incluidas, siguen funcionando: es uno de los objetivos del JEP.
Los números de PetClinic
El caso de estudio del JEP 545 usa Spring PetClinic en una máquina de 32 GB de memoria, con una carga sostenida de 30.000 peticiones por segundo y un límite de 20 ms para el P99:
- JDK 25 con
-Xms2M -Xmx20G: arranca en 5,86 s, pero tarda unos 80 s en calentar. - JDK 25 con
-Xms20G -Xmx20G -XX:+AlwaysPreTouch: calienta dentro de los 10 s de rampa, pero arranca en 9,45 s. - Con la propuesta y
-XX:+ZAdaptiveHeapSizing: 5,84 s de arranque y caliente en 10 s.
Es el caso de estudio de los autores, no una promesa para tu aplicación.
Lo que puede salirte mal
Los dos JEP lo reconocen. Si tu aplicación contaba con el heap inicial grande que ZGC daba por defecto en máquinas con mucha memoria, con 2 MB puede tardar más en calentar, y tocará volver a ajustar. Y con el dimensionado adaptativo activado, ese máximo del 100 % puede hacer que tu JVM use más memoria que antes y deje cortos a otros procesos.
Los dos JEP están en estado Targeted: asignados a JDK 28, pero su página todavía no los marca como entregados. Si quieres probarlos, sigue la página de JDK 28 y las builds de acceso anticipado.