Pregunta

Recientemente me encontré con este error en mi aplicación web:

java.lang.OutOfMemoryError:PermGen space

Se trata de un típico Hibernate/JPA + IceFaces/JSF ejecución de la aplicación en Tomcat 6 y JDK 1.6.Al parecer, esto puede ocurrir después de la reasignación de una aplicación un par de veces.

¿Cuál es la causa y qué se puede hacer para evitarlo?¿Cómo puedo solucionar el problema?

¿Fue útil?

Solución

La solución fue añadir estos indicadores para la JVM de la línea de comandos cuando Tomcat se inicia:

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

Usted puede hacer que al apagar el servicio tomcat, a continuación, entrar en el Tomcat/bin y ejecutar tomcat6w.exe.Bajo el "Java" ficha, agregar los argumentos para el "Java" Opciones del cuadro.Haga clic en "ACEPTAR" y, a continuación, reinicie el servicio.

Si obtiene un error el servicio especificado no existe como servicio instalado se debe ejecutar:

tomcat6w //ES//servicename

donde servicename es el nombre del servidor, como se ve en los servicios.msc

Fuente:orx que lo comente Eric Ágil Respuestas.

Otros consejos

Es mejor probar -XX:MaxPermSize=128M en lugar de -XX:MaxPermGen=128M.

No puedo decir el uso preciso de este grupo de memoria, pero lo que tiene que ver con el número de clases de carga en la JVM.(Por lo tanto la habilitación de clase de descarga para tomcat puede resolver el problema.) Si sus aplicaciones se genera y compila clases en la carrera es más probable que necesite un bloque de memoria más grande que el valor predeterminado.

Servidor de aplicaciones PermGen los errores que se producen después de múltiples implementaciones son la causa más probable de referencias a cabo por el contenedor en su viejo apps' cargadores de clases.Por ejemplo, el uso de un registro personalizado de nivel de clase hará que las referencias que se celebrará por el servidor de la aplicación del cargador de clases.Usted puede detectar estas inter-cargador de clases de fugas mediante el uso de modernas (JDK6+) JVM herramientas de análisis tales como jmap y jhat a mirar en los que las clases se mantienen en su aplicación, y el rediseño o eliminación de su uso.Sospechosos habituales son las bases de datos, registradores, y otra base-marco a nivel de las bibliotecas.

Ver Cargador de clases de fugas:el temido "de java.lang.OutOfMemoryError:PermGen space" excepción, y , especialmente, su seguimiento post.

Comunes errores que la gente comete es pensar que el montón de espacio y permgen space son los mismos, lo cual no es del todo cierto.Usted podría tener un montón de espacio restante en el montón, pero todavía se puede ejecutar fuera de la memoria permgen.

Las causas comunes de OutofMemory en PermGen es del cargador de clases.Cuando una clase se carga en la JVM, sus metadatos, junto con el cargador de clases, se mantiene en PermGen área y que va a ser el recolector de basura cuando el cargador de clases que les cargado está listo para la recolección de basura.En el Caso del cargador de clases tiene una pérdida de memoria de todas las clases cargadas por permanecerá en la memoria y hacer que permGen outofmemory una vez que se repita un par de veces.El ejemplo clásico es Java.lang.OutOfMemoryError:PermGen Space en Tomcat.

Ahora hay dos formas de solucionar esto:
1.Encontrar la causa de la Pérdida de Memoria o si hay alguna pérdida de memoria.
2.Aumentar el tamaño de PermGen Space mediante el uso de la JVM param -XX:MaxPermSize y -XX:PermSize.

También puede comprobar 2 Solución de Java.lang.OutOfMemoryError en Java para obtener más detalles.

Utilice el parámetro de línea de comandos -XX:MaxPermSize=128m para una JVM de Sun (obviamente la sustitución de 128 para cualquier tamaño que usted necesita).

Trate de -XX:MaxPermSize=256m y si persiste, intente -XX:MaxPermSize=512m

Yo agregó -XX: MaxPermSize = 128m (se puede probar que funciona mejor) para Argumentos de VM como estoy usando el ide eclipse.En la mayoría de los JVM, por defecto PermSize es alrededor de 64 MB el que se queda sin memoria si hay demasiadas clases o gran número de Cadenas en el proyecto.

Para eclipse, también se describe en respuesta.

PASO 1 :Haga doble Clic en el servidor tomcat en Servidores Ficha

enter image description here

PASO 2 : Abrir el lanzamiento de Conf y agregar -XX: MaxPermSize = 128m al final de los ya existentes VM argumentos.

enter image description here

He estado topando mi cabeza en contra de este problema, mientras que la implementación y la anulación de la implementación de una aplicación web compleja demasiado, y pensé que me gustaría añadir una explicación y mi solución.

Al implementar una aplicación en Apache Tomcat, un nuevo cargador de clases se crea para esa aplicación.El cargador de clases se utiliza a continuación para cargar todas las aplicaciones a las clases, y en undeploy, todo lo que se supone que vaya muy bien.Sin embargo, en realidad no es tan simple.

Una o más de las clases creadas durante la aplicación web en la vida tiene una referencia estática que, en algún lugar a lo largo de la línea, las referencias que el cargador de clases.Como la referencia es originalmente estática, ninguna cantidad de la recolección de basura se esta limpio de referencia hasta que el cargador de clases, y clases de todo lo que se carga, están aquí para quedarse.

Y después de un par de implementa de nuevo, nos encontramos con la OutOfMemoryError.

Ahora esto se ha convertido en un bastante serio problema.Yo podría asegurarse de que Tomcat se reinicia después de cada vuelva a implementar, pero que lleva todo el servidor, en vez de sólo la aplicación redesplegados, que a menudo no es factible.

Así que en su lugar he puesto juntos una solución en el código, que funciona en Apache Tomcat 6.0.No he probado en otros servidores de aplicaciones, y hay que destacar que esto es muy probable que no funcione sin modificación en cualquier otro servidor de aplicaciones.

También me gustaría decir que personalmente odio este código, y que nadie debe utilizar esto como una "solución rápida" si el código existente puede ser cambiado para el uso adecuado de apagado y métodos de limpieza.La única vez que esto se debe utilizar es que si hay una biblioteca externa su código es dependiente (En mi caso, se trataba de un cliente RADIUS) que no proporciona un medio para limpiar sus propias referencias estáticas.

De todos modos, con el código.Esto debería ser llamado en el punto donde la aplicación es la anulación de la implementación - como un servlet del método destroy o (el mejor enfoque) un ServletContextListener del contextDestroyed método.

//Get a list of all classes loaded by the current webapp classloader
WebappClassLoader classLoader = (WebappClassLoader) getClass().getClassLoader();
Field classLoaderClassesField = null;
Class clazz = WebappClassLoader.class;
while (classLoaderClassesField == null && clazz != null) {
    try {
        classLoaderClassesField = clazz.getDeclaredField("classes");
    } catch (Exception exception) {
        //do nothing
    }
    clazz = clazz.getSuperclass();
}
classLoaderClassesField.setAccessible(true);

List classes = new ArrayList((Vector)classLoaderClassesField.get(classLoader));

for (Object o : classes) {
    Class c = (Class)o;
    //Make sure you identify only the packages that are holding references to the classloader.
    //Allowing this code to clear all static references will result in all sorts
    //of horrible things (like java segfaulting).
    if (c.getName().startsWith("com.whatever")) {
        //Kill any static references within all these classes.
        for (Field f : c.getDeclaredFields()) {
            if (Modifier.isStatic(f.getModifiers())
                    && !Modifier.isFinal(f.getModifiers())
                    && !f.getType().isPrimitive()) {
                try {
                    f.setAccessible(true);
                    f.set(null, null);
                } catch (Exception exception) {
                    //Log the exception
                }
            }
        }
    }
}

classes.clear();

Alternativamente, usted puede cambiar a JRockit que el manejo de permgen de manera diferente, a continuación, la jvm de sun.Por lo general tiene un mejor rendimiento así.

http://www.oracle.com/technetwork/middleware/jrockit/overview/index.html

1) Aumentar el Tamaño de la Memoria PermGen

La primera cosa que uno puede hacer es hacer que el tamaño de la permanente generación montón de espacio más grande.Esto no se puede hacer con la habitual –Xms(conjunto inicial de tamaño de pila) y –Xmx(máximo tamaño de la pila) JVM argumentos, ya que como se mencionó, la generación permanente montón de espacio es completamente independiente de la normal Java Heap space, y estos argumentos espacio para el este de Java convencional montón de espacio.Sin embargo, hay argumentos similares que pueden ser utilizados(por lo menos con el Sol/OpenJDK jvm) para hacer que el tamaño de la permanente generación montón más grande:

 -XX:MaxPermSize=128m

Por defecto es de 64mb.

2) Activar El Barrido De

Otra manera de tomar el cuidado de que para el bien es para permitir que las clases para ser descargado de manera que su PermGen nunca se acabe:

-XX:+CMSClassUnloadingEnabled -XX:+CMSPermGenSweepingEnabled

Cosas como que trabajó magia para mí en el pasado.Una cosa sin embargo, hay una significativa del rendimiento de comercio en el uso de estos, ya que permgen barridos hará como un extra de 2 solicitudes por cada solicitud que usted hace o algo a lo largo de esas líneas.Usted necesita para equilibrar su uso con los equilibrios.

Usted puede encontrar los detalles de este error.

http://faisalbhagat.blogspot.com/2014/09/java-outofmemoryerror-permgen.html

El java.lang.OutOfMemoryError: PermGen el espacio de mensaje indica que la Generación Permanente del área en la memoria se ha agotado.

Ninguna de las aplicaciones Java se permite el uso de una cantidad limitada de memoria.La cantidad exacta de memoria de su aplicación en particular puede utilizar se especifica durante el arranque de la aplicación.

Memoria de Java está dividido en diferentes regiones que se puede ver en la siguiente imagen:

enter image description here

Metaspace:Un nuevo espacio de memoria es nacido

El JDK 8 de la JVM HotSpot es ahora utilizando el lenguaje de la memoria para la representación de metadatos de la clase y se llama Metaspace;similar a la de Oracle JRockit e IBM (JVM).

La buena noticia es que eso significa que no hay más java.lang.OutOfMemoryError: PermGen problemas de espacio y no hay necesidad de ajustar y supervisar este espacio de memoria más el uso de Java_8_Download o superior.

Yo tenía el problema de que estamos hablando aquí, mi escenario es en eclipse helios + tomcat + jsf y lo que estaban haciendo es implementar una aplicación simple para tomcat.Me estaba mostrando el mismo problema, resuelto de la siguiente manera.

En eclipse ir a servidores ficha haga doble clic en el servidor registrado en mi caso tomcat 7.0, se abre mi archivo General del servidor de registro de la información.En la sección "Información General" haga clic en el enlace "Abrir configuración de lanzamiento" , de esta forma se abre la ejecución de las opciones de servidor en los Argumentos de la ficha en la VM argumentos que se han añadido al final estas dos entradas

-XX: MaxPermSize = 512m
-XX: PermSize = 512m

y listo.

La respuesta más sencilla en estos días es el uso de Java 8.

Ya no se reserva memoria exclusivamente para PermGen space, permitiendo la memoria PermGen a co-mezclarse con la normal de la memoria de la piscina.

Tenga en cuenta que usted tendrá que quitar todos los no-estándar -XXPermGen...=... JVM parámetros de inicio si no quieres Java 8 que se quejan de que no hacen nada.

  1. Abierto tomcat7w de Tomcat bin del directorio o el tipo de Monitor Tomcat en el menú de inicio (se abre una ventana con pestañas con diversos servicios de información).
  2. En las Opciones de Java área de texto añada esta línea:

    -XX:MaxPermSize=128m
    
  3. Set Inicial del grupo de Memoria 1024 (opcional).
  4. Establecer el número Máximo de grupo de Memoria 1024 (opcional).
  5. Haga Clic En Aceptar.
  6. Reinicie el servicio Tomcat.

Perm gen espacio error se produce debido al gran espacio en lugar de jvm les brindó el espacio para ejecuta el código.La mejor solución para este problema en los sistemas operativos UNIX es cambiar alguna configuración en el archivo bash.Siguientes pasos resolver el problema.

Ejecutar el comando gedit .bashrc en la terminal.

Crear JAVA_OTPS variable con el valor siguiente:

export JAVA_OPTS="-XX:PermSize=256m -XX:MaxPermSize=512m"

Guarde el archivo bash.Ejecute el comando exec bash en la terminal.Reinicie el servidor.

Espero que este enfoque va a trabajar en su problema.Si utiliza una versión de Java menor que 8 este problema se produce a veces.Pero si el uso de Java 8 el problema nunca se produce.

El aumento de tamaño de Generación Permanente o ajustar GC parámetros NO será de ayuda si usted tiene una verdadera pérdida de memoria.Si su aplicación o algunos 3ª parte de la biblioteca que utiliza, fugas de clase cargadores de la única verdadera y permanente solución es encontrar esta pérdida y solucionarlo.Hay una serie de herramientas que pueden ayudar a usted, uno de los últimos es Plumbr, que acaba de publicar una nueva versión con las capacidades requeridas.

También si usted está utilizando log4j en su webapp, revise este párrafo en log4j documentación.

Parece que si usted está utilizando PropertyConfigurator.configureAndWatch("log4j.properties"), que causa pérdidas de memoria cuando se anula la implementación de su webapp.

Tengo una combinación de Hibernate+Eclipse RCP, trató de usar -XX:MaxPermSize=512m y -XX:PermSize=512m y parece ser que trabajan para mí.

Conjunto -XX:PermSize=64m -XX:MaxPermSize=128m.Más tarde usted también puede tratar de aumentar MaxPermSize.Espero que va a trabajar.El mismo funciona para mí.Configuración sólo MaxPermSize no funcionó para mí.

He intentado varias respuestas y la única cosa que lo que finalmente se hizo el trabajo fue esta configuración para que el compilador plugin en el pom:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>2.3.2</version>
    <configuration>
        <fork>true</fork>
        <meminitial>128m</meminitial>
        <maxmem>512m</maxmem>
        <source>1.6</source>
        <target>1.6</target>
        <!-- prevent PermGen space out of memory exception -->
        <!-- <argLine>-Xmx512m -XX:MaxPermSize=512m</argLine> -->
    </configuration>
</plugin>

espero que esta ayuda.

resuelto esto para mí también;sin embargo, me di cuenta de que el servlet reiniciar los tiempos eran mucho peor, así que, aunque fue mejor en la producción, es una especie de arrastre en el desarrollo.

La configuración de la memoria depende de la naturaleza de su aplicación.

¿Qué estás haciendo?

¿Cuál es la cantidad de transacciones precessed?

La cantidad de datos que se le carga?

etc.

etc.

etc

Probablemente usted podría perfil de su aplicación y comenzar la limpieza de algunos de los módulos de la aplicación.

Al parecer, esto puede ocurrir después de la reasignación de una aplicación un par de veces

Tomcat ha despliegue en caliente pero consume memoria.Pruebe a reiniciar el recipiente de vez en cuando.También se necesita saber la cantidad de memoria necesaria para ejecutar en el modo de producción, este parece un buen momento para que la investigación.

Dicen que la última rev de Tomcat (6.0.28 o 6.0.29) se encarga de la tarea de la recolocación de los servlets mucho mejor.

Me encuentro exactamente el mismo problema, pero por desgracia ninguna de las soluciones que se proponen realmente funcionó para mí.El problema no sucedió durante la implementación, y yo no era ni hacer ningún caliente implementaciones.

En mi caso el problema se ha producido cada vez en el mismo punto durante la ejecución de mi en la web de la aplicación, mientras que la conexión (a través de hibernate) a la base de datos.

En este enlace (también mencionado anteriormente) no proporcionar suficiente interior para resolver el problema.Mover el jdbc-(mysql)-controlador de la WEB-INF y dentro de la jre/lib/ext/ carpeta parece haber resuelto el problema.Esta no es la solución ideal, ya que la actualización a una nueva versión de JRE es necesario que vuelva a instalar el controlador.Otro candidato que podría causar problemas similares es log4j, por lo que es posible que desee mover de que uno así

Primer paso en tal caso es comprobar si el GC es descargar clases de PermGen.El estándar de la JVM es más bien conservador en este sentido, las clases son nacido para vivir para siempre.Así que una vez cargado, clases de permanecer en la memoria incluso si no hay ningún código es el uso de ellos.Esto puede convertirse en un problema cuando la aplicación crea un montón de clases de forma dinámica y de las clases generadas no son necesarios para períodos más largos.En tal caso, permitiendo que la JVM para descargar las definiciones de clase pueden ser útiles.Esto puede lograrse mediante la adición de un parámetro de configuración a sus secuencias de comandos de inicio:

-XX:+CMSClassUnloadingEnabled

Por defecto se establece en falso y así habilitar esta usted necesita para establecer explícitamente la siguiente opción en las opciones de Java.Si habilita CMSClassUnloadingEnabled, GC barrerá PermGen demasiado y quitar clases que ya no se utilizan.Tenga en cuenta que esta opción sólo funcionará cuando UseConcMarkSweepGC también está habilitado mediante la siguiente opción.Así que cuando se ejecuta ParallelGC o, Dios no lo quiera, Serie GC, asegúrese de que ha establecido su GC CMS especificando:

-XX:+UseConcMarkSweepGC

La asignación de Tomcat más memoria NO es la solución adecuada.

La solución correcta es hacer una limpieza después de que el contexto es destruido y recreado (el despliegue en caliente).La solución es detener las fugas de memoria.

Si tu Tomcat/Webapp Servidor está diciendo que no se pudo anular el registro de conductores (JDBC), luego anular el registro de ellos.Esto evitará las pérdidas de memoria.

Usted puede crear un ServletContextListener y configurar en su web.xml.Aquí está un ejemplo de ServletContextListener:

import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.apache.log4j.Logger;

import com.mysql.jdbc.AbandonedConnectionCleanupThread;

/**
 * 
 * @author alejandro.tkachuk / calculistik.com
 *
 */
public class AppContextListener implements ServletContextListener {

    private static final Logger logger = Logger.getLogger(AppContextListener.class);

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        logger.info("AppContextListener started");
    }

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        logger.info("AppContextListener destroyed");

        // manually unregister the JDBC drivers
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        while (drivers.hasMoreElements()) {
            Driver driver = drivers.nextElement();
            try {
                DriverManager.deregisterDriver(driver);
                logger.info(String.format("Unregistering jdbc driver: %s", driver));
            } catch (SQLException e) {
                logger.info(String.format("Error unregistering driver %s", driver), e);
            }

        }

        // manually shutdown clean up threads
        try {
            AbandonedConnectionCleanupThread.shutdown();
            logger.info("Shutting down AbandonedConnectionCleanupThread");
        } catch (InterruptedException e) {
            logger.warn("SEVERE problem shutting down AbandonedConnectionCleanupThread: ", e);
            e.printStackTrace();
        }        
    }
}

Y aquí puede configurar en su web.xml:

<listener>
    <listener-class>
        com.calculistik.mediweb.context.AppContextListener 
    </listener-class>
</listener>  

"Ellos" están equivocados porque me estoy quedando 6.0.29 y tengo el mismo problema, incluso después de ajustar todas las opciones.Como Tim Howland dijo anteriormente, estas opciones sólo posponer lo inevitable.Me permiten volver a implementar 3 veces antes de golpear el error en lugar de cada vez que me vuelva a implementar.

En caso de que usted está recibiendo esta en el IDE de eclipse, incluso después de ajustar los parámetros --launcher.XXMaxPermSize, -XX:MaxPermSize, etc, aún si usted está recibiendo el mismo error, lo más probable es que el eclipse es el uso de un buggy versión de JRE que habría sido instalado por algunas aplicaciones de terceros y establecer valores predeterminados.Estos buggy versiones no recoger la PermSize parámetros y por lo tanto no importa lo que pongan, aún así seguir recibiendo estos errores de memoria.Así, en su eclipse.ini agregar los siguientes parámetros:

-vm <path to the right JRE directory>/<name of javaw executable>

También asegúrese de establecer el valor predeterminado de JRE en las preferencias en el eclipse de la versión correcta de java.

La única forma en que ha funcionado para mí fue con el JRockit de la JVM.He MyEclipse 8.6.

La JVM montón de tiendas de todos los objetos generados por una ejecución de programa de Java.Java utiliza la new operador para crear objetos, y la memoria para los objetos nuevos se asigna en la pila en tiempo de ejecución.La recolección de basura es el mecanismo de forma automática la liberación de la memoria contenida en los objetos que ya no se hace referencia por el programa.

Estaba teniendo un problema similar.La mía es de JDK 7 + Maven 3.0.2 + Struts 2.0 + Google GUICE la inyección de dependencia basada en proyecto.

Siempre traté de correr mvn clean package comando, se mostraba el siguiente mensaje de error y "ERROR EN LA CONSTRUCCIÓN" ocurrió

org.apache.maven.infalible.util.SurefireReflectionException:java.lang.reflejar.InvocationTargetException;excepciones anidadas es java.lang.reflejar.InvocationTargetException:null java.lang.reflejar.InvocationTargetException Causado por:java.lang.OutOfMemoryError:PermGen space

He intentado todos los anteriores consejos útiles y trucos, pero por desgracia, ninguno funcionó para mí.Lo que funcionó para mí se describe paso a paso a continuación :=>

  1. Vaya a su pom.xml
  2. Búsqueda de <artifactId>maven-surefire-plugin</artifactId>
  3. Añadir un nuevo <configuration> elemento y, a continuación, <argLine> sub elemento en el que pasar -Xmx512m -XX:MaxPermSize=256m como se muestra a continuación =>

<configuration> <argLine>-Xmx512m -XX:MaxPermSize=256m</argLine> </configuration>

Espero que ayude, feliz de programación :)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top