Memoria Per Gem en aplicaciones Java

Memoria Per Gem en aplicaciones Java

| April 12, 2011 | 1 Comment

Nos habremos encontrado en algunas ocasiones en nuestras aplicaciones Java, referente a la memoria que consume esta, dos excepciones muy comunes:

java.lang.OutOfMemoryError: Java heap space
java.lang.OutOfMemoryError: PermGen space failure

En una entrada anterior, titulada Como configurar el uso de memoria de un servidor en Eclipse, ya comenté la solución por la que se puede optar para aumentar la memoria y resolver el error. Sin embargo, quería profundizar algo más acerca de la segunda de las excepciones.


¿Que es la memoria PermGen? Es la memoria que emplea la maquina virtual Java para almacenar el código estático de las aplicaciones que corren sobre ella. Y es bastante común que en aplicaciones J2EE, que hagan uso de servlets, jsp,… (sobre todo si la aplicación tiene un mantenimiento largo) tengamos problemas con esta memoria.

¿Cual es el límite por defecto de la memoria PermGen? El límite es 64MB.

¿Porque si el código de mi aplicación ocupa 1MB se puede producir esta excepción? Solamente las clases correspondientes al contenedor de aplicaciones ya ocupan un espacio en memoria de 30Mb aproximadamente. Seguimos teniendo de todas formas un margen bastante amplio, pero hay que sumar las librerías que se hayan añadido a la carpeta WEB-INF/lib de nuestra aplicación.

¿Que métodos existen para monitorizar la memoria Perm Gen de una aplicación? Voy a recomendar dos posibles opciones:

Primera opción: Usar herramientas intuitivas

Por ejemplo Lambda Probe. Básicamente, es una aplicación que se despliegua sobre el servidor de aplicaciones (Tomcat o Jboss). Permite mediante una interfaz gráfica monitorizar las aplicaciones que se estan ejecutando. En particular para acceder al consumo de memoria, se ha de buscar la pestaña System Information:

Información de sistema

Pulsando en el menú de la izquierda sobre Memory utilization, se obtiene una pantalla con información acerca del estado de los distintos tipos de memorias:

Consumo de memoria

Segunda opción: usar herramientas de consola

Por ejemplo, JPS y JSTAT. Son dos pequeñas utilidades incluidas dentro de la jdk Si por ejemplo usamos un sistema operativo linux, lo primero es identificar el proceso que corresponde a la ejecución de la máquina virtual. Con ese pid habrá de usarse el siguiente comando:

jstat -gcpermcapacity pid

Cuyo resultado puede ser algo parecido a:

PGCMN PGCMX PGC PC YGC FGC FGCT
8192,0 65536,0 25600,0 25600,0 24 4 0,457
En dichos resultados, nos interesan las tres primeras  columnas:
– PGCMN: memoria Perm Gen mínima asignada.
– PGCMAX: memoria Perm Gen máxima asignada.
– PGC:  memoria Perm Gen ocupada actualmente.
Si el valor en PGC se aproxima a PGCMAX, habría que plantearse la idea de incrementar la memoria máxima disponible Perm Gen por ejemplo añadiendo al arranque de la máquina virtual Java la opción:

-XX:MaxPermSize=256m

Puedes consultar la entrada que ya publique hace unos días acerca del tema:  Como configurar el uso de memoria de un servidor en Eclipse

Algunos sitios de referencia que os pueden ser útiles:

Sitio web del producto Lambda Probe.
Javadoc de Jstat.
Un poco más de información acerca del uso de memoria de la maquina virtual Java.
El blog de Rubensa: una entrada muy interesante con un análisis completo y detallado del problema.