Thread Dumps y Heap Dumps: la radiografía de la JVM

Cuando la JVM no habla, los dumps hablan por ella.

Thread dumps y heap dumps para diagnóstico de la JVM

La JVM es una caja negra extraordinariamente eficiente. Administra memoria, hilos, garbage collection y compilación JIT sin que tengas que pensar en ello — hasta que algo falla. Y cuando falla en producción, la JVM no te dice qué pasó. Tienes que preguntarle. Las herramientas para preguntar son dos: thread dumps y heap dumps.

He diagnosticado deadlocks a las 2 de la madrugada, memory leaks que tardaron semanas en manifestarse, y pools de threads saturados que derribaron plataformas enteras. En todos los casos, la respuesta estaba en un dump. El problema es que muchos ingenieros nunca han leído uno, y cuando lo necesitan, no saben por dónde empezar.

Thread Dumps: qué está haciendo cada hilo

Un thread dump es una captura instantánea del estado de todos los threads de la JVM en un momento dado. Cada thread aparece con su nombre, su estado, y su stack trace completo. Es la herramienta fundamental para diagnosticar problemas de concurrencia, contención de recursos y bloqueos.

Los estados que vas a encontrar son cuatro, y cada uno cuenta una historia diferente:

Cómo capturar un thread dump

Hay tres métodos principales, y los tres son seguros en producción. No detienen la JVM, no causan pausa significativa, y no requieren reinicio:

Un solo thread dump muestra un instante. Para diagnosticar problemas intermitentes, captura tres o cuatro con intervalos de 5-10 segundos. Los threads que aparecen en el mismo estado y la misma línea de código en todas las capturas son los sospechosos.

Patrones de diagnóstico en thread dumps

Después de leer cientos de thread dumps, los patrones se repiten. Estos son los más frecuentes:

Para análisis automatizado, herramientas como IBM Thread Analyzer y fastthread.io parsean el dump, agrupan threads por estado, detectan deadlocks y visualizan la contención. fastthread.io es particularmente útil porque funciona desde el navegador: subes el archivo y obtienes un informe inmediato.

Heap Dumps: qué hay en memoria

Si el thread dump muestra qué está haciendo la JVM, el heap dump muestra qué está almacenando. Es una captura completa del heap: cada objeto, su tipo, su tamaño, y sus referencias a otros objetos. Es la herramienta definitiva para diagnosticar memory leaks y presión de garbage collection.

Un heap dump puede pesar varios gigabytes — es proporcional al tamaño del heap configurado. Capturarlo causa una pausa en la JVM (stop-the-world) cuya duración depende del tamaño del heap. En producción, hay que ser consciente de este impacto.

Cómo capturar un heap dump

Análisis con Eclipse MAT

Eclipse Memory Analyzer Tool (MAT) es la herramienta estándar para analizar heap dumps. Es gratuita, robusta, y puede manejar dumps de decenas de gigabytes. Los tres análisis fundamentales son:

Patrones de memory leak

Los memory leaks en Java no son como en C — no es memoria no liberada. Son objetos que el garbage collector no puede liberar porque todavía tienen una referencia activa, aunque la aplicación ya no los necesite. Los patrones más comunes:

Caso real: memory leak en Sterling OMS

Un entorno de producción de IBM Sterling ejecutaba business processes que procesaban órdenes de compra. El heap crecía de forma constante: 4 GB tras arrancar, 6 GB después de 48 horas, OutOfMemoryError después de una semana. El equipo reiniciaba la JVM cada 5 días como "solución".

Configuramos -XX:+HeapDumpOnOutOfMemoryError y esperamos. Cuando el OOM llegó, analizamos el dump con Eclipse MAT. El Dominator Tree reveló que un solo objeto — una instancia de java.util.ArrayList — retenía 2.3 GB de heap. Esa lista vivía dentro de un cache de documentos procesados que nunca ejecutaba eviction.

El Leak Suspects de MAT señaló directamente la cadena: GC Root → ThreadLocal → BusinessProcessContext → DocumentCache → ArrayList con 1.2 millones de entradas. Cada documento procesado se añadía al cache para "reutilización" pero jamás se eliminaba.

La solución fue configurar un límite de entradas en el cache y un TTL de 30 minutos. El heap se estabilizó en 3.5 GB y no volvió a crecer. Sin el heap dump, el equipo habría seguido reiniciando la JVM indefinidamente.

No adivines qué pasa en la JVM. Mídelo. Un thread dump toma 2 segundos de capturar y puede ahorrarte horas de especulación. Un heap dump es la diferencia entre "creo que hay un leak" y "sé exactamente dónde está el leak".

Jorel del Portal

Jorel del Portal

Ingeniero de sistemas especializado en arquitectura de software empresarial y plataformas de alta disponibilidad.