Causas y solución de java.lang.OutOfMemoryError: PermGen space failure

La memoria de la Máquina Virtual se divide en varias regiones. Una de estas regiones es el PermGen, el área de memoria utilizada para, entre otras cosas, guardar el metadata de las clases como los atributos y sus tipos de datos, métodos etc. Esta memoria es de tipo non-heap. Las instancias de las clases se cargan en la memoria de tipo heap, a la que se van añadiendo y eliminando las instancias de las clases según se van utilizando y eliminándose por el recolector de basura (Garbage Collector, en adelante GC).

No vamos a entrar en el mecanismo de la carga y eliminación de clases en java porque excede este artículo, pero sí lo comentaremos brevemente para poder entender el porqué de la excepción OutOfMemoryException: para que una clase pueda ser eliminada por el recolector de basura (GC), es necesario que no esté referenciada por ninguna otra clase. Para que se pueda eliminar la memoria ocupada por una clase en el espacio PermGen, es necesario además que se elimine el classloader que cargó la clase.

El valor por defecto del espacio PermGen es de 64 Mb en la máquina virtual (VM) de Sun. Este valor es suficiente normalmente para las aplicaciones que corren de forma independiente. En el caso de una aplicación que corra en un servidor web tipo Tomcat o un servidor de aplicaciones, hay casos en los que este valor no es suficiente.

En primer lugar, es posible que la aplicación necesite más espacio por su propia arquitectura. Las librerías Spring e Hibernate son librerías grandes, que cargan muchas clases y además hacen uso de proxies y carga dinámica de clases que hacen uso del espacio PermGen por lo que puede que los 64Mb no sean suficientes. Este caso se da cuando la excepción con el error se produce nada mas arrancar el servidor web o de aplicaciones o al acceder a la aplicación. Para solventar este problema bastará con aumentar el tamaño máximo de la memoria de tipo PermGen según veremos más adelante.

En segundo lugar, la causa más probable de una excepción java.lang.OutOfMemoryError: PermGen space failure se produce cuando la aplicación se reinstala en el servidor sin reiniciar el servidor. La forma de reinstalar las aplicaciones es eliminando el classloader que cargó la aplicación por primera vez y creando un nuevo classloader para la nueva instancia de la aplicación. En teoría, esto proporciona una forma limpia de reinstalar aplicaciones, pero si el servidor web o de aplicaciones guarda una referencia al classloader antiguo, se produce una fuga de memoria (memory leak) y el resultado es que tendremos las clases de la aplicación cargadas dos veces en memoria. Es cuestión del número de recargas y de la memoria gastada por la aplicación el que se produzca la excepción  java.lang.OutOfMemoryError: PermGen space failure. En este caso no basta con aumentar el tamaño máximo de la memoria, ya que esto sólo retrasaría el problema a unas cuantas reinstalaciones más. En este caso la única solución consiste en averiguar la causa de la fuga de memoria. Esto también excede el contenido de este artículo, aunque lo intentarmos tratar con profundidad en otra ocasión. Por el momento sólo proporcionamos un enlace muy interesante, aunque en inglés, acerca de posibles causas de fugas de memoria en java: http://opensource.atlassian.com/confluence/spring/pages/viewpage.action?pageId=2669

Por último, a continuación incluimos el argumento que es necesario incluir al arrancar la máquina virtual para especificar el tamaño de esta región PermGen en Mb, XX:MaxPermSize=128m para el tamaño máximo y XX:PermSize=128m para que la máquina virtual ya arranque con este tamaño y no tenga que reservar más espacio en tiempo de ejecución.

4 Respuestas a “Causas y solución de java.lang.OutOfMemoryError: PermGen space failure”

  1. conejo dijo:

    Hola, estuve leyendo tu artículo, yo tengo aparentemente el mismo problema, el mensaje que me sale es el siguiente: «java.lang.OutOfMemoryError: Java heap space». La información que considero relevante es: Total Heap Memory: 65088 KB; Free Heap Memory: 39705 KB; Max Heap Memory: 65088 KB; tengo un sistema basado en Vista.

    El tema es el siguiente, he visto por todos lados y particularmente en este artículo, que se puede aumentar la memoria para evitar este problema, pero no se cómo hacerlo, no tengo ni idea de programación en Java.

    Por lo tanto, si puedes decirme PASO A PASO como lo logro te estaré muy agradecido.

  2. conejo dijo:

    Ya lo solucioné, de todas formas muchas gracias.

  3. admin dijo:

    Hola,

    Precisamente estábamos preparando una entrada para explicar cómo aumentar la memoria de la máquina virtual. La subiremos en los próximos días

    ProgramacionEnJava.com

  4. Programacion en JAVA » Aumentar el tamaño de la máquina virtual en Java dijo:

    […] Por último, recordamos que resolver el problema de una excepción de tipo java.lang.OutOfMemoryError simplemente aumentando el tamaño de la memoria virtual puede retrasar el problema pero no evitarlo si el problema es una fuga de memoria. Puedes encontrar más información aquí. […]

Deje una respuesta

Se debe registrar para escribir un comentario.