Diferentes formas de capturar volcados de almacenamiento dinámico de Java

Head dump es una instantánea de todos los objetos que están en la memoria de la JVM en un momento determinado. Son muy útiles para solucionar problemas de pérdida de memoria y optimizar el uso de la memoria en aplicaciones Java. Los volcados de cabecera generalmente se almacenan en archivos ‘hprof’ de 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. Ahora revisaremos múltiples herramientas y enfoques para generar una joroba en la cabeza, y mostraremos la principal diferencia entre ellos.

El JDK viene con varias herramientas para capturar head dumps de diferentes maneras. 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 los próximos pasos, veremos cómo usar estas herramientas para capturar head dumps.

Métodos:

  1. jmap
  2. jcmd
  3. JVisualVM
  4. Captura de volcado de cabeza automáticamente
  5. JMX

Analicemos cada uno de los métodos mencionados anteriormente en detalle para comprenderlos mejor. 

Método 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 cabeza usando jmap, necesitamos usar la opción de volcado:

 jmap -dump:[live],format=b,file=<file-path> <pid>

Junto a esa opción, debemos especificar varios parámetros:

  • live: si se establece, solo imprime objetos que tienen referencias activas y descarta los que están listos para ser recolectados como 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 Java

Nota: podemos obtener fácilmente el PID de un proceso 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 en su lugar.

Ejemplo

jmap -dump:live,format=b,file=/tmp/dump.hprof 12587

Método 2: jcmd

‘jcmd’ es una herramienta muy completa que funciona enviando requests de comando a la JVM. Tenemos que usarlo en la misma máquina donde se está ejecutando el proceso 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 <pid> GC.head_dump <file-path>

Podemos ejecutarlo con el mismo parámetro que usamos antes:

jcmd 12587  GC.head_dump  /tmp/dump.hprof

Al igual que con jmap, el volcado generado está en formato binario.

Método 3: JVisualVM

JVisualVM es una herramienta con una interfaz gráfica de usuario que nos permite monitorear, solucionar problemas y crear perfiles de 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 cabeza. Si hacemos clic con el botón derecho en un proceso Java y seleccionamos la opción “Head Dump”, la herramienta creará un volcado de pila y lo abrirá en una nueva pestaña:

Como notamos arriba, podemos encontrar la ruta del archivo creado en la sección «Información básica». A partir de JDK9, VISUAL VM no se incluye en las distribuciones Oracle JDK y Open JDK. Por lo tanto, si usamos Java 9 o versiones más nuevas, podemos obtener JVisualVM del sitio del proyecto de código abierto de Visual VM.

Método 4: captura el volcado de cabeza automáticamente

Todas las herramientas que hemos mostrado anteriormente están destinadas a capturar volcados de cabeza manualmente en un momento específico. En algunos casos, queremos obtener un volcado de almacenamiento dinámico cuando se produce un java.lang.OutOfMemoryError para que nos ayude a investigar el error:

Para estos casos, Java proporciona la opción de línea de comandos HeadDumpOnOutOfMemoryError que genera un volcado de pila cuando se lanza un java.lang.OutOfMemoryError:

java -XX:+HeadDumpOnOutOfMemoryError

Por defecto, almacena el volcado en un archivo java_pid<pid>.hprof en el directorio donde estamos ejecutando la aplicación. Si queremos especificar otro archivo o directorio podemos configurarlo en la opción HeadDumpPath:

java -XX:+HeadDumpOnOutOfMemoryError -XX:HeapDumpPath=<file-or-dir-path>

Cuando nuestras aplicaciones se queden sin memoria usando esta opción, podremos ver en los registros el archivo creado que contiene el volcado de pila:

java.lang.OutOfMemoryError: Requested array size exceeds VM limit
During heap to java_pid12587.hprof...
  Exception in thread "main" Head 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)

En este ejemplo anterior, se escribió en el archivo java_pid2587.hprof. Como podemos ver, esta opción es muy útil y no hay sobrecarga al ejecutar una aplicación con esta opción. Por lo tanto, es muy recomendable usar esta opción siempre, especialmente en producción. Por último, esta opción también se puede especificar en tiempo de ejecución utilizando HotSpotDiagnostic MBean . Para hacerlo, podemos usar JConsole y establecer la opción de VM HeapDumpOnOutOfMemoryError en verdadero:

Método 5: JMX

El último enfoque que cubriremos en este artículo es el uso de JMX. Usaremos el HotSpotDiagnostic MBean que presentamos brevemente en la sección anterior. Este MBean proporciona un método dumpHeap que acepta 2 parámetros:

  • archivo de salida: la ruta del archivo para el volcado. El archivo debe tener la extensión hprof
  • live: si se establece en verdadero, volcará solo los objetos activos en la memoria, como hemos visto antes en jmap

Ahora aquí hay 2 formas de invocar este método para capturar un volcado de cabeza:

La forma más fácil de usar HotSpotDiagnostic MBean es usar un cliente JMX como JConsole. Si abrimos JConsole y nos conectamos a un proceso Java en ejecución, podemos navegar a la pestaña MBeans y encontrar HotSpotDiagnostic en com.sun.management. En estas operaciones podemos encontrar el método dumpHead que hemos descrito antes:

Como se muestra, solo necesitamos introducir los parámetros archivo de salida y vivir en los campos de texto p0 y p1 para realizar la operación dumpHeap.

Implementación: Manera de capturar el volcado del montón

La otra forma de usar HotSpotDiagnostic MBean es invocándolo mediante programación desde código Java. Para hacerlo, necesitamos obtener una instancia de MBeanServer para obtener un MBean que esté registrado en la aplicación. Después de eso, simplemente necesitamos obtener una instancia de HotSpotDiagnosticMXBean y llamarlo método dumpHeap.

public static void dumpHeap(String filePath, boolean live) throws IOException {
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
HotSpotDiagnosticMXBean mxBean = ManagementFactory.newPlatformMXBeanProxy
  (server, "com.sun.management:type=HotSpotDiagnos
  tic",
HotSpotDiagnosticMXBean.class);
mxBean.dumpHeap(filePath, live);
}

Tenga en cuenta que un archivo hprof no se puede sobrescribir. Por lo tanto, debemos tener esto en cuenta al crear una aplicación que imprima volcados de almacenamiento dinámico. Si no lo hacemos, obtendremos una excepción:

Exception in thread "main" java.io.IOException: File exists 
at sun.management.HotSpotDianostic.dumpHeap0(Native Method) at 
sun.management.HotSpotDiagnostic.dumpHeap(HotSpotDiagnostic.java:60)

Conclusión: la última regla que debemos recordar siempre es usar la opción HeapDumpOnOutOfMemoryError siempre que se ejecuten aplicaciones Java.

Publicación traducida automáticamente

Artículo escrito por akashpandit1103 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *