Recientemente me encontré con este error en mi aplicación web:
java.lang.OutOfMemoryError: espacio PermGen
Es una aplicación típica de Hibernate / JPA + IceFaces / JSF que se ejecuta en Tomcat 6 y JDK 1.6. Aparentemente, esto puede ocurrir después de volver a implementar una aplicación varias veces.
¿Qué lo causa y qué se puede hacer para evitarlo? ¿Cómo soluciono el problema?
Respuestas:
La solución fue agregar estos indicadores a la línea de comandos de JVM cuando se inicia Tomcat:
Puede hacerlo cerrando el servicio tomcat, yendo al directorio Tomcat / bin y ejecutando tomcat6w.exe. En la pestaña "Java", agregue los argumentos al cuadro "Opciones de Java". Haga clic en "Aceptar" y luego reinicie el servicio.
Si obtiene un error, el servicio especificado no existe como un servicio instalado que debe ejecutar:
donde servicename es el nombre del servidor como se ve en services.msc
Fuente: comentario de orx sobre las respuestas ágiles de Eric .
fuente
Será mejor que lo intentes en
-XX:MaxPermSize=128M
lugar de hacerlo-XX:MaxPermGen=128M
.No puedo decir el uso preciso de este grupo de memoria, pero tiene que ver con el número de clases cargadas en la JVM. (Por lo tanto, habilitar la descarga de clases para tomcat puede resolver el problema). Si sus aplicaciones generan y compilan clases en ejecución, es más probable que necesite un grupo de memoria más grande que el predeterminado.
fuente
Los errores de PermGen del servidor de aplicaciones que ocurren después de múltiples implementaciones probablemente sean causados por las referencias que el contenedor contiene en los cargadores de clases de sus aplicaciones anteriores. Por ejemplo, el uso de una clase de nivel de registro personalizada hará que las referencias sean retenidas por el cargador de clases del servidor de aplicaciones. Puede detectar estas fugas entre cargadores entre clases utilizando herramientas modernas de análisis JVM (JDK6 +) como jmap y jhat para ver qué clases continúan en su aplicación y rediseñando o eliminando su uso. Los sospechosos habituales son bases de datos, registradores y otras bibliotecas de nivel de marco base.
Consulte las filtraciones de Classloader: la temida excepción "java.lang.OutOfMemoryError: PermGen space" , y especialmente su publicación de seguimiento .
fuente
Los errores comunes que cometen las personas es pensar que el espacio de almacenamiento dinámico y el espacio permgen son iguales, lo cual no es del todo cierto. Podría tener mucho espacio restante en el montón, pero aún puede quedarse sin memoria en permgen.
Las causas comunes de OutofMemory en PermGen es ClassLoader. Cada vez que se carga una clase en JVM, todos sus metadatos, junto con Classloader, se mantienen en el área de PermGen y se recolectarán cuando el Classloader que los cargó esté listo para la recolección de basura. En el caso, Classloader tiene una pérdida de memoria que todas las clases cargadas permanecerán en la memoria y causarán que permGen quede fuera de memoria una vez que lo repita un par de veces. El ejemplo clásico es Java.lang.OutOfMemoryError: PermGen Space en Tomcat .
Ahora hay dos formas de resolver esto:
1. Encuentre la causa de la pérdida de memoria o si hay alguna pérdida de memoria.
2. Aumente el tamaño del espacio PermGen utilizando JVM param
-XX:MaxPermSize
y-XX:PermSize
.También puede consultar 2 Solution of Java.lang.OutOfMemoryError en Java para obtener más detalles.
fuente
-XX:MaxPermSize and -XX:PermSize
? No puedo encontrarcatalina.bat
. Mi versión de Tomcat es5.5.26
.Utilice el parámetro de línea de comando
-XX:MaxPermSize=128m
para una JVM de Sun (obviamente sustituyendo 128 por el tamaño que necesite).fuente
Intenta
-XX:MaxPermSize=256m
y si persiste, prueba-XX:MaxPermSize=512m
fuente
XX:MaxPermSize=1024m
:)Yo añadí
-XX: MaxPermSize = 128m
(se puede experimentar lo que funciona mejor) a argumentos de VM como yo estoy usando Eclipse IDE. En la mayoría de JVM, PermSize predeterminado es de alrededor de 64 MB que se queda sin memoria si hay demasiadas clases o una gran cantidad de cadenas en el proyecto.Para eclipse, también se describe en la respuesta .
PASO 1 : haga doble clic en el servidor Tomcat en la pestaña Servidores
PASO 2 : Abra el lanzamiento de Conf y agréguelo
-XX: MaxPermSize = 128m
al final de los argumentos de VM existentes .fuente
Me he estado enfrentando a este problema mientras desplegaba y desplegaba una aplicación web compleja también, y pensé en agregar una explicación y mi solución.
Cuando implemento una aplicación en Apache Tomcat, se crea un nuevo ClassLoader para esa aplicación. El ClassLoader se usa para cargar todas las clases de la aplicación, y en la anulación de la implementación, se supone que todo desaparecerá bien. Sin embargo, en realidad no es tan simple.
Una o más de las clases creadas durante la vida de la aplicación web contienen una referencia estática que, en algún lugar a lo largo de la línea, hace referencia al ClassLoader. Como la referencia es originalmente estática, ninguna cantidad de recolección de basura limpiará esta referencia: el ClassLoader y todas las clases cargadas están aquí para quedarse.
Y después de un par de redespliegues, nos encontramos con OutOfMemoryError.
Ahora esto se ha convertido en un problema bastante serio. Podría asegurarme de que Tomcat se reinicie después de cada nueva implementación, pero eso elimina todo el servidor, en lugar de solo la aplicación que se vuelve a implementar, lo que a menudo no es factible.
Entonces, en su lugar, armé una solución en código, que funciona en Apache Tomcat 6.0. No he probado en ningún otro servidor de aplicaciones, y debo enfatizar que es muy probable que esto no funcione sin modificaciones en ningún otro servidor de aplicaciones .
También me gustaría decir que personalmente odio este código, y que nadie debería usarlo como una "solución rápida" si el código existente se puede cambiar para usar los métodos adecuados de apagado y limpieza . El único momento en que esto debería usarse es si hay una biblioteca externa de la que depende su código (en mi caso, era un cliente RADIUS) que no proporciona un medio para limpiar sus propias referencias estáticas.
De todos modos, adelante con el código. Esto debería llamarse en el punto donde la aplicación se está desplegando, como el método de destrucción de un servlet o (el mejor enfoque) el método contextDestroyed de ServletContextListener.
fuente
El
java.lang.OutOfMemoryError: PermGen
mensaje de espacio indica que el área de la generación permanente en la memoria está agotada.Cualquier aplicación Java puede utilizar una cantidad limitada de memoria. La cantidad exacta de memoria que puede usar su aplicación particular se especifica durante el inicio de la aplicación.
La memoria Java está separada en diferentes regiones que se pueden ver en la siguiente imagen:
Metaspace: nace un nuevo espacio de memoria
El JDK 8 HotSpot JVM ahora está usando memoria nativa para la representación de metadatos de clase y se llama Metaspace; similar a Oracle JRockit e IBM JVM.
La buena noticia es que significa que no habrá más
java.lang.OutOfMemoryError: PermGen
problemas de espacio y que ya no tendrá que ajustar y monitorear este espacio de memoria utilizando Java_8_Download o superior.fuente
1) Aumento del tamaño de la memoria PermGen
Lo primero que se puede hacer es aumentar el tamaño del espacio dinámico de generación permanente. Esto no se puede hacer con los argumentos JVM habituales –Xms (establecer el tamaño de almacenamiento dinámico inicial) y –Xmx (establecer el tamaño de almacenamiento dinámico máximo), ya que, como se mencionó, el espacio de almacenamiento dinámico de generación permanente está completamente separado del espacio de almacenamiento dinámico Java normal, y estos argumentos establecen El espacio para este espacio de almacenamiento dinámico Java normal. Sin embargo, existen argumentos similares que pueden usarse (al menos con Sun / OpenJDK jvms) para aumentar el tamaño del montón de generación permanente:
El valor predeterminado es 64 m.
2) Habilitar barrido
Otra forma de solucionarlo definitivamente es permitir que se descarguen las clases para que su PermGen nunca se agote:
Cosas como esa funcionaron magia para mí en el pasado. Sin embargo, una cosa es que hay un importante rendimiento en el uso de esos, ya que los barridos permgen harán 2 solicitudes adicionales por cada solicitud que realice o algo por el estilo. Tendrá que equilibrar su uso con las compensaciones.
Puede encontrar los detalles de este error.
http://faisalbhagat.blogspot.com/2014/09/java-outofmemoryerror-permgen.html
fuente
Alternativamente, puede cambiar a JRockit que maneja permgen de manera diferente que jvm de sun. En general, también tiene un mejor rendimiento.
http://www.oracle.com/technetwork/middleware/jrockit/overview/index.html
fuente
java.lang.OutOfMemoryError: There is insufficient native memory
lugar.Tuve el problema del que estamos hablando aquí, mi escenario es eclipse-helios + tomcat + jsf y lo que estabas haciendo es implementar una aplicación simple en tomcat. Estaba mostrando el mismo problema aquí, lo resolví de la siguiente manera.
En eclipse, vaya a la pestaña de servidores, haga doble clic en el servidor registrado en mi caso tomcat 7.0, se abre la información de registro general de mi servidor de archivos. En la sección "Información general", haga clic en el enlace "Abrir configuración de inicio" , esto abre la ejecución de las opciones del servidor en la pestaña Argumentos en los argumentos de VM agregados al final de estas dos entradas
y listo.
fuente
La respuesta más simple en estos días es usar Java 8.
Ya no reserva memoria exclusivamente para el espacio PermGen, permitiendo que la memoria PermGen se mezcle con el grupo de memoria normal.
Tenga en cuenta que tendrá que eliminar todos los
-XXPermGen...=...
parámetros de inicio JVM no estándar si no desea que Java 8 se queje de que no hacen nada.fuente
En el área de texto Opciones de Java, agregue esta línea:
fuente
El error de espacio de generación permanente ocurre debido al uso de espacio grande en lugar de jvm proporcionó espacio para ejecutar el código.
La mejor solución para este problema en los sistemas operativos UNIX es cambiar alguna configuración en el archivo bash. Los siguientes pasos resuelven el problema.
Ejecute el comando
gedit .bashrc
en la terminal.Crear
JAVA_OTPS
variable con el siguiente valor:Guarda el archivo bash. Ejecute el comando exec bash en la terminal. Reinicia el servidor.
Espero que este enfoque funcione en su problema. Si utiliza una versión de Java inferior a 8, este problema se produce a veces. Pero si usa Java 8, el problema nunca se produce.
fuente
Aumentar el tamaño de la generación permanente o ajustar los parámetros del GC NO ayudará si tiene una pérdida de memoria real. Si su aplicación o alguna biblioteca de terceros que utiliza, filtra los cargadores de clases, la única solución real y permanente es encontrar esta filtración y solucionarla. Hay varias herramientas que pueden ayudarlo, una de las recientes es Plumbr , que acaba de lanzar una nueva versión con las capacidades requeridas.
fuente
Además, si está utilizando log4j en su aplicación web, consulte este párrafo en la documentación de log4j .
Parece que si está utilizando
PropertyConfigurator.configureAndWatch("log4j.properties")
, puede causar pérdidas de memoria cuando desinstala su aplicación web.fuente
Tengo una combinación de Hibernate + Eclipse RCP, intenté usar
-XX:MaxPermSize=512m
y-XX:PermSize=512m
parece estar funcionando para mí.fuente
Conjunto
-XX:PermSize=64m -XX:MaxPermSize=128m
. Más adelante también puede intentar aumentarMaxPermSize
. Espero que funcione. Lo mismo funciona para mí. La configuración soloMaxPermSize
no funcionó para mí.fuente
Intenté varias respuestas y lo único que finalmente hizo el trabajo fue esta configuración para el complemento del compilador en el pom:
Espero que esto ayude.
fuente
jrockitresolvió esto por mí también; Sin embargo, noté que los tiempos de reinicio del servlet eran mucho peores, por lo que si bien fue mejor en producción, fue un obstáculo para el desarrollo.
fuente
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 precesadas?
¿Cuántos datos estás cargando?
etc.
etc.
etc.
Probablemente podría perfilar su aplicación y comenzar a limpiar algunos módulos de su aplicación.
Tomcat tiene despliegue en caliente pero consume memoria. Intente reiniciar su contenedor de vez en cuando. También necesitará saber la cantidad de memoria necesaria para ejecutar en modo de producción, este parece ser un buen momento para esa investigación.
fuente
Dicen que la última versión de Tomcat (6.0.28 o 6.0.29) maneja la tarea de volver a desplegar servlets mucho mejor.
fuente
Me encuentro exactamente con el mismo problema, pero desafortunadamente ninguna de las soluciones sugeridas realmente funcionó para mí. El problema no ocurrió durante la implementación, y tampoco estaba haciendo implementaciones en caliente.
En mi caso, el problema ocurrió cada vez en el mismo punto durante la ejecución de mi aplicación web, mientras me conectaba (a través de hibernación) a la base de datos.
Este enlace (también mencionado anteriormente) proporcionó suficientes elementos internos para resolver el problema. Mover el controlador jdbc- (mysql) fuera de WEB-INF y hacia la carpeta jre / lib / ext / parece haber resuelto el problema. Esta no es la solución ideal, ya que actualizar a un JRE más nuevo requeriría que reinstale el controlador. Otro candidato que podría causar problemas similares es log4j, por lo que es posible que desee mover ese también
fuente
El primer paso en tal caso es verificar si el GC puede descargar clases de PermGen. La JVM estándar es bastante conservadora a este respecto: las clases nacen para vivir para siempre. Entonces, una vez cargadas, las clases permanecen en la memoria incluso si ya no las usa ningún código. Esto puede convertirse en un problema cuando la aplicación crea muchas clases dinámicamente y las clases generadas no son necesarias por períodos más largos. En tal caso, puede ser útil permitir que la JVM descargue definiciones de clase. Esto se puede lograr agregando solo un parámetro de configuración a sus scripts de inicio:
De forma predeterminada, esto se establece en falso y, por lo tanto, para habilitarlo, debe establecer explícitamente la siguiente opción en las opciones de Java. Si habilita CMSClassUnloadingEnabled, GC también barrerá PermGen y eliminará las clases que ya no se usan. Tenga en cuenta que esta opción solo funcionará cuando UseConcMarkSweepGC también esté habilitado usando la opción a continuación. Entonces, cuando ejecute ParallelGC o, Dios no lo quiera, Serial GC, asegúrese de haber configurado su GC en CMS especificando:
fuente
Asignar más memoria a Tomcat NO es la solución adecuada.
La solución correcta es hacer una limpieza después de que el contexto se destruya y se vuelva a crear (la implementación en caliente). La solución es detener las pérdidas de memoria.
Si su servidor Tomcat / Webapp le indica que no pudo anular el registro de los controladores (JDBC), anule el registro. Esto detendrá las pérdidas de memoria.
Puede crear un ServletContextListener y configurarlo en su web.xml. Aquí hay un ejemplo de ServletContextListener:
Y aquí lo configura en su web.xml:
fuente
"Ellos" están equivocados porque estoy ejecutando 6.0.29 y tengo el mismo problema incluso después de configurar todas las opciones. Como Tim Howland dijo anteriormente, estas opciones solo posponen lo inevitable. Me permiten volver a implementar 3 veces antes de dar con el error en lugar de cada vez que vuelvo a implementar.
fuente
En caso de que obtenga esto en el eclipse IDE, incluso después de configurar los parámetros
--launcher.XXMaxPermSize
,-XX:MaxPermSize
etc., aún si obtiene el mismo error, lo más probable es que el eclipse esté utilizando una versión defectuosa de JRE que habría sido instalada por algunos aplicaciones de terceros y configuradas por defecto. Estas versiones con errores no recogen los parámetros de PermSize y, por lo tanto, no importa lo que establezca, seguirá recibiendo estos errores de memoria. Entonces, en su eclipse.ini agregue los siguientes parámetros:También asegúrese de establecer el JRE predeterminado en las preferencias en el eclipse a la versión correcta de Java.
fuente
La única forma que funcionó para mí fue con JRockit JVM. Tengo MyEclipse 8.6.
El montón de JVM almacena todos los objetos generados por un programa Java en ejecución. Java utiliza el
new
operador para crear objetos, y la memoria para nuevos objetos se asigna en el montón en tiempo de ejecución. La recolección de basura es el mecanismo de liberar automáticamente la memoria contenida en los objetos a los que el programa ya no hace referencia.fuente
Estaba teniendo un problema similar. El mío es JDK 7 + Maven 3.0.2 + Struts 2.0 + Proyecto basado en inyección de dependencia de Google GUICE.
Cada vez que intentaba ejecutar
mvn clean package
comandos, se muestra siguiente error y "FALLO construir" producidoIntenté todos los consejos y trucos útiles anteriores, pero desafortunadamente ninguno funcionó para mí. Lo que funcionó para mí se describe paso a paso a continuación: =>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
elemento y luego un<argLine>
subelemento en el que pase-Xmx512m -XX:MaxPermSize=256m
como se muestra a continuación =><configuration> <argLine>-Xmx512m -XX:MaxPermSize=256m</argLine> </configuration>
Espero que ayude, feliz programación :)
fuente