java - solucion - ¿Qué se puede hacer con la excepción ''PermGen out of space'' en la aplicación web Tomcat-Spring-Hibernate?
java.lang.outofmemoryerror: permgen space tomcat (8)
Tenemos una aplicación web que utiliza Spring-Hibernate para conservar los datos de los usuarios registrados en la base de datos Oracle. La aplicación funciona bien en un entorno de desarrollo, pero cuando lo copiamos en un entorno real con muchos más datos, falló. Inicialmente, la aplicación se inicia normalmente, pero después de algunas acciones se produjo la excepción ''PermGen out of space''.
Comencé a buscar en los foros de Google, Spring e Hibernate, pero no ayuda. Hay muchas discusiones sobre este error, pero para cada solución, hay personas que dicen: ''Funciona'' y otras personas dicen ''No funciona''.
Por ejemplo, muchas personas ofrecen aumentar el parámetro JVM -XX:MaxPermSize
, otros dicen que no funciona. Hay publicaciones que dicen que el problema en el uso de la biblioteca javassist y otros y la biblioteca cglib necesitaba ser usado. Otros dicen que el problema está en cglib.
Utilizamos Java1.5_0_09, Spring 2.5 con javaassist3.4.GA, Tomcat 5.5 como contenedor web y Oracle 10g como base de datos.
¿Alguien puede explicarme qué causa este problema y cómo resolverlo?
Como dice skaffman, la propiedad -XX: MaxPermSize sí funciona, sin embargo, a veces puede tener un problema subyacente que el aumento del límite solo puede diferir.
¿Has visto esta nota ? Me ayudó a resolver un problema similar una vez. Para resumir el enlace:
- Ponga el controlador JDBC en común / lib (como dice la documentación de Tomcat ) y no en WEB-INF / lib
- No coloque el inicio de sesión común en WEB-INF / lib ya que Tomcat ya lo reinicia
Corrí en el mismo problema, y leí que Tomcat es el culpable en esta situación.
Luego me cambié al embarcadero y todo salió genial, y la aplicación se despliega / ejecuta como se esperaba. Así que si Tomcat no es un deber, entonces sugeriría Jetty.
Debe tener en cuenta que algunas versiones de Tomcat tienen pérdidas de memoria en la redistribución de la guerra. Me sucedió en Tomcat 6.0.x.
Como se sugiere aumentar el MaxPermSize , esta es una solución temporal para su máquina de desarrollo, y cuando obtiene el error, después de 2-3 días, simplemente reinicie el servidor. En producción no es tan simple. Por lo tanto, esto funciona para el desarrollo , pero este enfoque no funciona para la producción , donde se deben solucionar los problemas de fugas de memoria.
Para descubrir las fugas, use la aplicación jconsole que viene con jdk 1.6 y 1.5. Puede vincularse a un proceso y ver la memoria utilizada a lo largo del tiempo.
También puedes leer estos:
- http://blogs.oracle.com/fkieviet/entry/classloader_leaks_the_dreaded_java
- http://blogs.oracle.com/fkieviet/entry/how_to_fix_the_dreaded
- http://java.sun.com/developer/technicalArticles/J2SE/monitoring/index.html
- http://my.opera.com/karmazilla/blog/2007/03/13/good-riddance-permgen-outofmemoryerror
- http://my.opera.com/karmazilla/blog/2007/03/15/permgen-strikes-back
El -XX:MaxPermSize
funciona, solo tienes que obtener el valor correcto. El valor predeterminado, creo, es 32 MB para la máquina virtual en modo cliente y 64 MB para la máquina virtual en modo servidor. Sugiero configurarlo a 256mb, si tiene la memoria:
java -XX:MaxPermSize=256m
El problema se produce porque Spring e Hibernate pueden hacer un uso intensivo de las clases generadas por el tiempo de ejecución, a veces muchas. Todas estas clases generadas entran en el grupo de memoria PermGen, por lo que si usa esos marcos, a menudo necesita aumentar su PermGen a grandes cantidades.
He visto este problema con Hibernate (usado sin Spring). El problema era que estábamos creando una instancia de SessionFactory para cada solicitud de usuario en lugar de crear una instancia única para toda la vida de la aplicación.
Utilicé el perfilador de YourKit para investigar esto y descubrir el problema.
Si está ejecutando jdk6, puede usar la aplicación jconsole para monitorear el uso de la memoria de la aplicación e investigar más.
Otra vía a seguir es usar un generador de perfiles, yo uso JProfiler, y miro la aplicación con eso. Le dirá exactamente de dónde viene el problema.
Todas las respuestas aquí se relacionan con el problema de PermGen que ocurre debido a varios reinicios de la aplicación web, pero en este caso el problema ya ocurre en la primera implementación después de que Tomcat se reinicie, por lo que no puede ser el problema de las referencias de ClassLoader o el registro de bienes comunes.
Visual GC, ahora parte de JDK 6, ofrece una representación gráfica muy buena de la memoria en tiempo real. Puedes ver lo que está sucediendo con los espacios eden, generacionales y permanentes. Simplemente no verás por qué.
ACTUALIZACIÓN: Es bin / jvisualvm.exe en mi JDK 1.6.0_13 distro. Dale el PID del proceso que quieres monitorear.