El tamaño de todas estas regiones, incluyendo el área PermGen, se establece durante el lanzamiento de la JVM. Si tu en el inicio no estableces el tamaño, se utilizarán los valores predeterminados que usa la plataforma.
Entonces, si te aparece: "java.lang.OutOfMemoryError PermGen space" indicará que el tamaño permanente del área en memoria se ha agotado.
Ejemplo de java.lang.OutOfMemoryError
import javassist.ClassPool; public class MicroGenerator { public static void main(String[] args) throws Exception { for (int i = 0; i < 100_000_000; i++) { generate("eu.plumbr.demo.Generated" + i); } } public static Class generate(String name) throws Exception { ClassPool pool = ClassPool.getDefault(); return pool.makeClass(name).toClass(); } }
En este ejemplo, el código fuente esta iterando sobre un loop y generando clases en tiempo de ejecución. La complejidad de la generación de claes es atendida por la libreria javassit. Al lanzar el código anterior, se mantendrá la creación de nuevas clases y esto hará que se carguen las definiciones en el espacio Permgen hasta que llegue al límite y de esta forma se lanzará el error "java.lang.OutOfMemoryError: Permgen space"
Solución para java.lang.OutOfMemoryError
-XX:MaxPermSize=512m
Este parámetro de configuración indica a la JVM que debe permitir al espacio PermGen crecer hasta 512 MB antes de lanzar una OutOfMemoryError.
La segunda posibilidad es permitir al GarbageCollector (GC) descargar las clases de PermGen. La JVM estándar tiene un estilo conservador, toda clase que nace debe existir para siempre. Así una vez cargadas, las clases permanecen en la memoria incluso aunque no se vuelva usar jamás.
Esto puede convertirse en un problema cuando la aplicación está creando un montón de clases de forma dinámica y las clases generadas no son necesarias por largos periodos de tiempo. En tal caso, permitir a la JVM descargar las clases puede ser de gran ayuda. Esto se logra agregando un nuevo parámetro de configuración en el inicio:
-XX:+CMSClassUnloadingEnabled
Por defecto, se establece a false y para poder habilitarlo es necesario establecerlo de manera explícita siguiendo las opciones de Java Options.
Se habilita CMSClassUnloadingEnabled, la GC limpiará el PermGen y eliminará cualquier clase que no se utiliza. Tenga en cuenta, que esta opción sólo funciona cuando UseConcMarkSweepGC también se habilita.
-XX:+UseConcMarkSweepGC
Advertencia: Antes de usar estos dos parámetros para proporcionar una solución rápida, ten encuentra que solamente estas enmascarando el error, lo que realmente importa es el detectar si las clases que se instancias deben estar o no y encontrar una solución a ello.
Por ejemplo, si realmente quieres arreglar la fuga en la memoria PermGen, podrías utilizar el siguiente Servlet Context Listener para detectar fallos:
// ServletContextListener public class JdbcDriverLeakPreventer implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { //Nothing to do } @Override public void contextDestroyed(ServletContextEvent sce) { ClassLoader applicationClassLoader = this.getClass().getClassLoader(); Enumeration driverEnumeration = DriverManager.getDrivers(); while (driverEnumeration.hasMoreElements()) { Driver driver = driverEnumeration.nextElement(); ClassLoader driverClassLoader = driver.getClass().getClassLoader(); if (driverClassLoader != null && driverClassLoader.equals(applicationClassLoader)){ try { DriverManager.deregisterDriver(driver); } catch (SQLException e) { e.printStackTrace(); //TODO Replace with your exception handling } } } } }
Este Servlet Listener debe ser registrado en el web.xml de tu aplicación.
user.package.JdbcDriverLeakPreventer
Hay diferentes formas de investigar que ha ocupado espacio PermGen en su JVM y si los objetos tengan alguna razón válida para llenarlo.
Otra opción: pasarse a Java8 donde ya por fin se han cargado el PermGen :-D (se utiliza el Heap para cargar las definiciones de clases)
ResponderEliminarLa verdad es un avance. Lamentablemente el proyecto en el cual me encuentro trabajando actualmente, apenas, esta migrando a Java 7. Por lo tanto, es bueno tener información de los errores del PermGen que van apareciendo en las diferentes fases del proyecto.
ResponderEliminar