Nivel 2 · 20 min
Memoria JVM
Entender cómo la JVM gestiona la memoria es esencial para diagnosticar OutOfMemoryErrors, ajustar el rendimiento del GC y diseñar sistemas que manejen millones de objetos eficientemente.
Áreas de memoria de la JVM
La memoria de la JVM se divide en: Heap (generaciones Young + Old para asignación de objetos), Stack (por hilo, almacena frames con variables locales), Metaspace (metadata de clases, bytecode de métodos, desde Java 8 reemplaza PermGen — crece dinámicamente, acotado por -XX:MaxMetaspaceSize), Code Cache (código nativo compilado por JIT), y áreas off-heap como Direct Buffers. Cada región tiene modos de falla distintos: heap → OutOfMemoryError: Java heap space, metaspace → OutOfMemoryError: Metaspace.
Generaciones Young y Old, TLAB
La generación Young (Eden + dos espacios Survivor S0/S1) es donde se asignan todos los nuevos objetos. Eden se particiona en Thread-Local Allocation Buffers (TLABs) — cada hilo obtiene un chunk privado de Eden, permitiendo asignación sin sincronización. Los objetos que sobreviven un número configurable de GC menores (-XX:MaxTenuringThreshold, por defecto 15) se promueven a la generación Old. Un GC menor colecta solo Young; un GC mayor/full colecta todo.
Carga de clases
La JVM carga clases de forma lazy en el primer uso a través de la jerarquía de class loaders: Bootstrap → Extension/Platform → Application. Cada class loader mantiene su propio namespace — dos clases cargadas por loaders diferentes son distintas aunque sean idénticas. La carga de clases es la fuente de ClassCastException entre boundaries de loaders y de leaks de metaspace en entornos dinámicos.
Code example
// Verificar regiones de memoria JVM en runtime
Runtime rt = Runtime.getRuntime();
long heapUsed = rt.totalMemory() - rt.freeMemory();
long heapMax = rt.maxMemory();
// Flags JVM clave para ajuste de memoria
// -Xms512m -Xmx2g # heap inicial y máximo
// -XX:NewRatio=2 # Old:Young = 2:1
// -XX:MaxMetaspaceSize=256m # acotar metaspace
// -XX:+PrintGCDetails # log GC detallado (Java 8)
// -Xlog:gc* # logging unificado (Java 9+)