#4sysadmins

Inicio » GNU/Linux » Monitorizar procesos con JConsole (3/3): tipos de memoria JVM

Monitorizar procesos con JConsole (3/3): tipos de memoria JVM

Últimas Entradas

Follow #4sysadmins on WordPress.com

Cuando ejecutamos una aplicación java esta es ejecutada sobre la JVM (Java Virtual Machine) la cual es capaz de aceptar opciones en tiempo de ejecución o definidas en el archivo de configuración del entorno de java. Estas opciones no son mas que una serie de parámetros capaces de modificar su comportamiento y con ello el rendimiento de la aplicación.

 

Existen diferentes tipos de argumentos:

  • Argumentos estándar : no suelen cambiar de una versión de JDK a otra. Si quieres conocer estos argumentos prueba a ejecutar java -help
  • Argumentos no estándar: Si pueden cambiar de una versión de JDK a otra. Para conocerlos basta con ejecutar el comando java -X
  • Argumentos ocultos: Argumentos experimentales que pueden variar en función del OS y de la versión de la JDK. Comienzan por -XX

Bueno ya sabemos que existen parámetros que modifican el comportamiento de nuestra JVM y con ello de nuestra aplicación. Vamos a dejar el estudio de los parámetros para mas adelante y vamos a ver ahora que información nos ofrece la JConsole con respecto al comportamiento de nuestra aplicación.

 

Información disponible en JConsole

Una vez que hemos conectado a nuestro proceso java mediante JConsole bien de forma local (ver entrada 1/3) o en remoto (ve entrada 2/3), veremos que se presenta un panel con seis pestañas:

  • Summary/Overview : Muestra cuatro gráficas; Uso de la memoria, los hilos del proceso, las clases cargadas y el uso de la CPU
  • Memory : Información detallada sobre el uso de la memoria. Igualmente aporta gráficas y “combos” para seleccionar un tipo de memoria concreta
  • Threads : Información detallada e individual del uso de hilos. Igualmente muestra su propia gráfica
  • Classes : Informa sobre el número de clases cargadas y descargadas.
  • VM Summary : Muestra información sobre la máquina virtual; como el uso de hilos, memoria consumida y algunos parámetros del OS
  • MBeas : Aquí se presenta una serie de directorios en árbol que contiene los métodos y clases que permiten controlar el proceso java. Ya vimos en la primera entrada que esto corresponde a la cala de instrumentación.

De todas las pestañas nos vamos a centrar tan solo en tres de ellas y especialmente en la pestaña “Memory“.

 

Overview

A través de las gráficas que se nos presenta podremos evaluar y tener una impresión de lo que está ocurriendo en tiempo de ejecución e incluso seleccionar una granularidad de tiempo mediante el “Time Range” que por defecto se encuentra seleccionado en All.

overview10min

En la imagen vemos lo ocurrido durante un rango de 10min con respecto a la CPU, memoria, los hilos activos y las clases cargadas

 

VMSumary

Esta pestaña muestra información de gran interés como por ejemplo el tiempo que lleva nuestra aplicación en ejecución (Uptime), el Current heap size, información sobre los componentes físicos de la máquina, como la memoria total, la memoria física disponible, la swap, el número de procesadores, etc…

Al final del todo podemos también conocer los argumentos con los que nuestra aplicación ha sido ejecutada “VM arguments“y las rutas de donde se están cargando librerías “Library path“.

vmsumary

 

Memory

Esta quizás sea la pestaña mas importante de todas, o al menos la que nos va a ayudar a comprender como se está comportando nuestra aplicación con respecto al uso de memoria.

En la parte superior encontramos dos combos y un botón “Perform GC“. El primer combo nos permite seleccionar un área de memoria concreto, el segundo un rango de tiempo y el botón efectuará al hacer click sobre él una recolección de basura.

memory

En la parte inferior, bajo la gráfica, veremos a la derecha unos medidores de tipo barra que representan el % de uso de cada una de las área de memoria. Si hacemos click sobre “Perfom GC” veremos como estos medidores reducen su porcentaje debido a que se ha realizado una recolección de basura, esto es, los objetos que han dejado de ser referenciados por otros serán eliminados mientras que el resto pasará al pool “Old generation” (veremos esto en breves de forma mas concisa).

A la izquierda de los medidores encontramos un recuadro con la fecha, la memoria usada dentro de un área seleccionado, la memoria comprometida (Committed), la máxima y los tiempos del GC.

 

Estado de la memoria

  • Init: Es un valor de memoria que no aparece en el gráfico de la pestaña “Memory” y que referencia a la cantidad inicial de memoria (en Kbytes) que la JVM solicita al OS al inicio.
  • Memoria usada: Es la cantidad de memoria (en Kb) que actualmente se encuentra utilizando nuestro proceso java. Cuando el valor de la memoria usada es mas o menos igual a la memoria comprometida es cuando mayor recolección de basura se produce.
  • Memoria comprometida (Committed): representa la cantidad de memoria (en Kbytes) que está garantizada para ser utilizada por la JVM. Esta cantidad de memoria suele ser variable a lo largo de la ejecución de la JVM ya que es liberada y solicitada al OS. Como mínimo será siempre igual a la utilizada y durante la mayor parte del tiempo será superior. Solo la cantidad de memoria commited es la que se encuentra disponible para utilizar. Si el tamaño de la memoria comprometida es mayor al tamaño de memoria física disponible, parte de esta será swapeada lo que supondrá una desaceleración del GC. Experimentaremos entonces una degradación en el rendimiento de la aplicación.
  • Max: Representa la cantidad máxima de memoria (en Kbytes) que puede ser utilizada por la JVM. La cantidad de memoria usada o comprometida será igual o menor a este valor.

Tamaño de pila
+———————————————+
+//////////////// |                                  +
+//////////////// |                                  +
+———————————————+

|——–|
init
|—————|
used
|—————————|
committed
|———————————————|
Max

 

Áreas de memoria

Bueno ahora que sabemos interpretar la información de estas pestañas, vamos a conocer los área de memoria existentes y por último (al final de la entrada) veremos los parámetros que nos ayudarán a modificar el tamaño de estas áreas.

Heap Memory

Representa la cantidad de memoria disponible para todos los hilos de ejecución del proceso. La heap memory es dividida en dos grupos, memoria de nueva generación y memoria de vieja generación (young & old generations). Los nuevos objetos son creados en la young heap memory y son movidos a la old heap memory cuando han sobrevivido al recolector de basura, lo que indicaría que son objetos aún referenciados por otros.

La young memory ocupa poco tamaño del heap pero es altamente activa. Esto está así organizado para que se pueda asignar de forma rápida memoria a los nuevos objetos y producir frecuentes recolecciones de basura que no tengan un fuerte impacto en el rendimiento de la aplicación. Por su parte la old generation contiene a los objetos de mayor vida en un área normalmente bastante mayor que el young area memory pero mucho menos activo. Las recolecciones de basura en la old generation ocurren con menos frecuencia pero pueden tener un impacto mucho mayor en el rendimiento de las aplicaciones, sobre todo si los hilos de la JVM son pausados durante la recolección, ya que se trabaja con un volumen mayor de datos.

Dentro de la Heap memory encontramos los siguientes pool:

  • Par Eden Space: Se define dentro del grupo de memorias de nueva generación (young generation) y representa al pool de memoria inicialmente asignada para la mayoría de los objetos. Casi todos los objetos suelen morir en este espacio de memoria.
  • Par Survivor Space: Al igual que Eden, se define dentro del grupo de memorias de nueva generación y representa al pool de memoria que contiene a los objetos que han sobrevivido al recolector de basura, es decir objetos que aun siguen siendo referenciados. Obviamente deben de ser menos, por lo cual en la gráfica el tamaño de este pool de memoria solo será superior al del Eden Space tras un GC.
  • Old Gen: Este pool de memoria se define como memoria de vieja generación debido a que solo contiene los objetos que han sobrevivido durante un tiempo al GC. Es decir objetos que son normalmente referenciados durante la ejecución del proceso. Cuando este espacio de memoria se llena, se produce un GC que con frecuencia es mucho mas lento debido a que se tratan todos los objetos vivos.

Non-Heap Memory

Este área de memoria es creado al inicio de la JVM y almacena classes, metadatos, código y constructores. Un incremento considerable en este área de memoria puede indicar problemas

 

El recolector de basura

Garbage collector es un administrador de memoria. Un objeto permanecerá cargado en memoria siempre que esté siendo referenciado por otro, diremos entonces que este objeto esta vivo. Cuando un objeto deja de ser referenciado se etiqueta como basura y por lo tanto puede ser limpiado para liberar espacio del heap para nuevos objetos. Esta acción mas la reorganización de los objetos restante es la labor que desempeña el GC.

Importante: Si el GC sufre embotellamientos, deberemos de ajustar los tamaños de los espacios de memoria. Con JConsole podemos ver el comportamiento de estos espacios y determinar cual sufre y cual no. Además podremos ver las métricas de configuración del GC desde la pestaña MBeans > java.lang > GarbageCollector > Attributes

 

Parámetros de la JVM

A continuación defino algunos de los parámetros mas importantes a modificar para conseguir un buen rendimiento en nuestra aplicación.

Heap Memory

  • -Xmx representa el tamaño máximo de memoria que pudiera llegar a alcanzar la JVM en la que es ejecutada nuestra aplicación. Si la aplicación necesitase mas de la especificada en este parámetro nos encontraremos con el error OutOfMemoryError.
  • -Xms marca la cantidad de memoria asignada a la JVM cuando iniciamos la aplicación. Este valor suele ajustarse a la mitad o al valor exacto del especificado en Xmx.
  • -Xss indica la cantidad de memoria disponible para cada hilo de ejecución. Un valor bajo en este parámetro puede provocar excepciones del tipo java.lang.StackOverflowError. Debemos de tener cuidado al aumentar el valor de este parámetro si encontramos la excepción anterior, pues un valor alto puede ser contraproducente, ya que podría impedir la creación de nuevos hilos de ejecución.
  • -Xmn controla la cantidad de memoria dinámica que puede consumir el área de memoria de nueva generación. Si definimos un valor bajo, el GC se ejecutará con mas frecuencia (quizás en su mayoría de ejecuciones no estemos limpiando nada) mientras que un valor alto provocará que hilos que no son referenciados de forma persistente y que deberían de ser limpiados, pasen al área de memoria de vieja generación.

Non-Heap Memory

  • XX:PermSize: Tamaño inicial de la memoria permanente (Non-Heap).
  • XX:MaxPermSize: Indica la cantidad máxima de memoria Non-Heap. Un error conocido como consecuencia del valor aquí definido es java.lang.OutOfMemoryError: PermGen space. Podremos evitar este error si aumentamos el valor de este parámetro.

Recolector de basura (GC)

  • XX:+UseSerialGC: Activa el recolector de copia en serie. Utiliza un solo hilo para copiar los objetos que sobreviven en el espacio de Eden (Pool Eden Space) tras un GC, al pool espacio de supervivientes (Pool Survivor Space) y de este al área de memoria de vieja generación (Old Gen) cuando estima que el objeto lleva un tiempo suficiente en la young memory.
  • XX:+UseParallelGC: A diferencia del recolector de copia en serie (SerialGC), ParallelGC utiliza múltiples hilos en paralelo.
  • XX:+UseParallelOldGC: Se combina con el parámetro anterior para utilizar la paralelización en el Old Gen
  • XX:+UseAdaptiveSizePolicy: Se combina junto con los dos parámetros anteriores y sirve para ajustarse al tamaño. Mejora el rendimiento del GC.
  • XX:+UseParNewGC: En este caso el GC trabaja de forma paralela pero dispone de mejoras con respecto al tratamiento de los objetos almacenados en el área de memoria de vieja generación que hace que trabaje de forma concurrente. Este parámetro está obsoleto en versiones 8 y 9 de JDK.

 


Deja un comentario, Gracias!

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: