2009-09-20 20 views
41

Estoy desarrollando en la plataforma elevadora estándar (maven y embarcadero). Estoy en repetidas ocasiones (una vez cada dos días) conseguir esto:Problemas de PermGen con el elevador y el embarcadero

Exception in thread "[email protected]" java.lang.OutOfMemoryError: PermGen space 
2009-09-15 19:41:38.629::WARN: handle failed 
java.lang.OutOfMemoryError: PermGen space 

Esto está en mi entorno de desarrollo. No es un problema porque puedo seguir reiniciando el servidor. En el despliegue, no estoy teniendo estos problemas, así que no es un problema real. Tengo curiosidad.

No sé demasiado sobre la JVM. Creo que estoy en lo cierto al pensar que la memoria de generación permanente es para cosas como clases y cadenas internas. Lo que recuerdo es un poco mezclado con el modelo de memoria .NET ...

¿Alguna razón por la que esto está sucediendo? ¿Los valores predeterminados son increíblemente bajos? ¿Tiene que ver con todos los objetos auxiliares que Scala tiene que crear para objetos Function y cosas similares de FP? Cada vez que reinicio Jetty con un código recién escrito (cada pocos minutos), me imagino que volverá a cargar clases, etc. Pero aun así, no puede ser así, ¿no? ¿Y la JVM no debería poder tratar con un gran número de clases?

Saludos

Joe

+1

Como se mencionó en la https://web.archive.org/web/20150105090518/http://www.scala-blogs.org/2007/12/scala-statically-typed-dynamic-language. Artículo html: "El recolector de basura generacional de la JVM está optimizado para situaciones como esta y debido a que los objetos creados implícitamente son efímeros, obtendrán GC muy bien". pero si esos objetos no tienen corta vida, esa es otra historia. – VonC

Respuesta

44

De this post:

Esta excepción se produjo por una simple razón:
la permgenspace es donde las propiedades de clase, tales como métodos, campos, anotaciones, y también variables estáticas, etc. se almacenan en Java VM, pero este espacio tiene la particularidad de no ser limpiado por el recolector de basura. Así que si su aplicación web usa o crea muchas clases (estoy pensando en generaciones dinámicas de clases), es probable que haya encontrado este problema. Aquí están algunas soluciones que me ayudaron a deshacerse de esta excepción:

  • -XX:+CMSClassUnloadingEnabled: esta configuración permite la recolección de basura en el permgenspace
  • -XX:+CMSPermGenSweepingEnabled: permite que el recolector de basura para eliminar incluso las clases de la memoria
  • -XX:PermSize=64M -XX:MaxPermSize=128M: aumenta la cantidad de memoria asignada a la permgenspace

puede ser que esto podría ayudar.

Editar julio de 2012 (casi 3 años después):

Ondra Žižka comentarios (y he actualizado la respuesta anterior):

JVM 1.6.0_27 dice: Utilice:

  • CMSClassUnloadingEnabled (Ya se haya descargado la clase cuando se usa CMS GC)
  • en lugar de CMSPermGenSweepingEnabled en el futuro

Ver todo Hotspot JVM Options - The complete reference para mroe.

+1

Gracias. Pensé que el problema se resolvería ajustando el comportamiento del GC o el tamaño de PermGen.Realmente estoy buscando una razón específica por la cual (/ if) Lift engarzaría objetos PermGen. – Joe

+1

Puede deberse a una generación de clase dinámica realizada por Lift. – VonC

+3

JVM 1.6.0_27 dice: Por favor, use 'CMSClassUnloadingEnabled' en lugar de' CMSPermGenSweepingEnabled' en el futuro. –

1

La generación permanente es donde la JVM pone cosas que probablemente no será (basura) recogidos como cargadores de clases personalizados.

Dependiendo de lo que esté desplegando, la configuración de la potencia permanente puede ser baja. Algunas aplicaciones y/o combinación de contenedores contienen algunas pérdidas de memoria, por lo que cuando una aplicación queda sin desplegar a veces algunas cosas como cargadores de clases no se recopilan, lo que resulta en llenar el espacio Perm generando el error que está teniendo.

Por desgracia, en la actualidad la mejor opción en este caso es máximo el espacio permanente con la siguiente bandera JVM (ejemplo para el tamaño 192m perm):

-XX:MaxPermSize=192M (or 256M) 

La otra opción es asegurarse de que o bien el contenedor o el marco no pierden memoria.

+0

Tiene que haber un '=' entre MaxPermSize y 192m. –

2

La lista de correo (http://groups.google.com/group/liftweb/) es el foro de soporte oficial de Lift, y donde podrá obtener una mejor respuesta. No conozco los pormenores de su configuración de desarrollo (no entra en detalles), pero supongo que está recargando su guerra en Jetty sin realmente reiniciarla. El ascensor no realiza una generación dinámica de clases (como lo sugiere VonC más arriba), pero Scala compila cada cierre como una clase separada. Si agrega y quita cierres a su código en el transcurso de varios días, es posible que se carguen demasiadas clases y que nunca se descarguen y ocupen espacio permanente. Te sugiero que habilites las opciones opciones de JVM mencionadas por VonC arriba y veas si ayudan.

+1

Gracias. Normalmente publico en el grupo de Google, pero pensé que podría darle una oportunidad a StackOverflow. Intentaremos aumentar los números. – Joe

3

Esto se debe a la recarga de clases que sugirió. Si está utilizando muchas bibliotecas, etc. la suma de las clases crecerá rápidamente para cada reinicio. Intente controlar su instancia de embarcadero con VisualVM para obtener una visión general del consumo de memoria al volver a cargar.

12

Si ve esto al ejecutar mvn jetty:run, configure MAVEN_OPTS.

Para Linux:

export MAVEN_OPTS="-XX:+CMSClassUnloadingEnabled -XX:PermSize=256M -XX:MaxPermSize=512M" 
mvn jetty:run 

Para Windows:

set "MAVEN_OPTS=-XX:+CMSClassUnloadingEnabled -XX:PermSize=256M -XX:MaxPermSize=512M" 
mvn jetty:run 

debe estar bien ahora. Si no, aumente -XX:MaxPermSize.

También puede poner estos permanentemente en su entorno.