1. Introducción
En este artículo, mostraremos diferentes formas de capturar un volcado de pila en Java.
Un volcado de pila es una instantánea de todos los objetos que están en la memoria en la JVM en un momento determinado . Son muy útiles para solucionar problemas de pérdida de memoria y optimizar el uso de memoria en aplicaciones Java.
Los volcados de pila generalmente se almacenan en archivos hprof en formato binario. Podemos abrir y analizar estos archivos usando herramientas como jhat o JVisualVM. Además, para los usuarios de Eclipse es muy común usar MAT.
En las siguientes secciones, veremos varias herramientas y enfoques para generar un volcado de pila y mostraremos las principales diferencias entre ellos.
2. Herramientas JDK
El JDK viene con varias herramientas para capturar volcados de pila de diferentes formas. Todas estas herramientas se encuentran en la carpeta bin dentro del directorio de inicio de JDK . Por lo tanto, podemos iniciarlos desde la línea de comandos siempre que este directorio esté incluido en la ruta del sistema.
En las siguientes secciones, mostraremos cómo usar estas herramientas para capturar volcados de pila.
2.1. jmap
jmap es una herramienta para imprimir estadísticas sobre la memoria en una JVM en ejecución. Podemos usarlo para procesos locales o remotos.
Para capturar un volcado de pila usando jmap, necesitamos usar la opción de volcado :
jmap -dump:[live],format=b,file=
Junto con esa opción, debemos especificar varios parámetros:
- live : si se establece, solo imprime los objetos que tienen referencias activas y descarta los que están listos para la recolección de basura. Este parámetro es opcional
- format = b : especifica que el archivo de volcado estará en formato binario. Si no se establece, el resultado es el mismo
- archivo : el archivo donde se escribirá el volcado
- pid : id del proceso de Java
Un ejemplo sería así:
jmap -dump:live,format=b,file=/tmp/dump.hprof 12587
Recuerde que podemos obtener fácilmente el pid de un proceso de Java usando el comando jps .
Tenga en cuenta que jmap se introdujo en el JDK como una herramienta experimental y no es compatible. Por lo tanto, en algunos casos, puede ser preferible utilizar otras herramientas.
2.2. jcmd
jcmd es una herramienta muy completa que funciona enviando solicitudes de comando a la JVM. Tenemos que usarlo en la misma máquina donde se ejecuta el proceso de Java.
Uno de sus muchos comandos es GC.heap_dump . Podemos usarlo para obtener un volcado de pila simplemente especificando el pid del proceso y la ruta del archivo de salida:
jcmd GC.heap_dump
Podemos ejecutarlo con los mismos parámetros que usamos antes:
jcmd 12587 GC.heap_dump /tmp/dump.hprof
Al igual que con jmap, el volcado generado está en formato binario.
2.3. JVisualVM
JVisualVM es una herramienta con una interfaz gráfica de usuario que nos permite monitorear, solucionar problemas y perfilar aplicaciones Java . La GUI es simple pero muy intuitiva y fácil de usar.
Una de sus muchas opciones nos permite capturar un volcado de pila. Si hacemos clic derecho en un proceso de Java y seleccionamos la opción "Heap Dump" , la herramienta creará un heap dump y lo abrirá en una nueva pestaña:

Observe que podemos encontrar la ruta del archivo creado en la sección "Información básica" .
A partir de JDK 9, Visual VM no se incluye en las distribuciones de Oracle JDK y Open JDK. Por lo tanto, si usamos Java 9 o versiones más recientes, podemos obtener JVisualVM del sitio del proyecto de código abierto de Visual VM.
3. Capture un volcado de pila automáticamente
All the tools that we've shown in the previous sections are intended to capture heap dumps manually at a specific time. In some cases, we want to get a heap dump when a java.lang.OutOfMemoryError occurs so it helps us investigate the error.
For these cases, Java provides the HeapDumpOnOutOfMemoryError command-line option that generates a heap dump when a java.lang.OutOfMemoryError is thrown:
java -XX:+HeapDumpOnOutOfMemoryError
By default, it stores the dump in a java_pid.hprof file in the directory where we're running the application. If we want to specify another file or directory we can set it in the HeapDumpPath option:
java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=
When our application runs out of memory using this option, we'll be able to see in the logs the created file that contains the heap dump:
java.lang.OutOfMemoryError: Requested array size exceeds VM limit Dumping heap to java_pid12587.hprof ... Exception in thread "main" Heap dump file created [4744371 bytes in 0.029 secs] java.lang.OutOfMemoryError: Requested array size exceeds VM limit at com.baeldung.heapdump.App.main(App.java:7)
In the example above, it was written to the java_pid12587.hprof file.
As we can see, this option is very useful and there is no overhead when running an application with this option. Therefore, it's highly recommended to use this option always, especially in production.
Finally, this option can also be specified at runtime by using the HotSpotDiagnostic MBean. To do so, we can use JConsole and set the HeapDumpOnOutOfMemoryError VM option to true:

We can find more information about MBeans and JMX in this article.
4. JMX
The last approach that we'll cover in this article is using JMX. We'll use the HotSpotDiagnostic MBean that we briefly introduced in the previous section. This MBean provides a dumpHeap method that accepts 2 parameters:
- outputFile: the path of the file for the dump. The file should have the hprof extension
- live: if set to true it dumps only the active objects in memory, as we've seen with jmap before
In the next sections, we'll show 2 different ways to invoke this method in order to capture a heap dump.
4.1. JConsole
The easiest way to use the HotSpotDiagnostic MBean is by using a JMX client such as JConsole.
If we open JConsole and connect to a running Java process, we can navigate to the MBeans tab and find the HotSpotDiagnostic under com.sun.management. In operations, we can find the dumpHeap method that we've described before:

As shown, we just need to introduce the parameters outputFile and live into the p0 and p1 text fields in order to perform the dumpHeap operation.
4.2. Programmatic Way
The other way to use the HotSpotDiagnostic MBean is by invoking it programmatically from Java code.
To do so, we first need to get an MBeanServer instance in order to get an MBean that is registered in the application. After that, we simply need to get an instance of a HotSpotDiagnosticMXBean and call its dumpHeap method.
Let's see it in code:
public static void dumpHeap(String filePath, boolean live) throws IOException { MBeanServer server = ManagementFactory.getPlatformMBeanServer(); HotSpotDiagnosticMXBean mxBean = ManagementFactory.newPlatformMXBeanProxy( server, "com.sun.management:type=HotSpotDiagnostic", HotSpotDiagnosticMXBean.class); mxBean.dumpHeap(filePath, live); }
Notice that an hprof file cannot be overwritten. Therefore, we should take this into account when creating an application that prints heap dumps. If we fail to do so we'll get an exception:
Exception in thread "main" java.io.IOException: File exists at sun.management.HotSpotDiagnostic.dumpHeap0(Native Method) at sun.management.HotSpotDiagnostic.dumpHeap(HotSpotDiagnostic.java:60)
5. Conclusion
In this tutorial, we've shown multiple ways to capture a heap dump in Java.
Como regla general, debemos recordar usar la opción HeapDumpOnOutOfMemoryError siempre al ejecutar aplicaciones Java. Para otros fines, cualquiera de las otras herramientas se puede utilizar perfectamente siempre que tengamos en cuenta el estado no admitido de jmap.
Como siempre, el código fuente completo de los ejemplos está disponible en GitHub.