¿Qué causa PermGen OutOfMemoryError en JBoss?

8

¿Cuál es la causa subyacente de un PermGen OutOfMemoryError en JBoss?

Estoy ejecutando JBoss AS 4.2.2 en mi entorno de desarrollo, y esto ocurre después de volver a implementar mi aplicación web una gran cantidad de veces.

El blog de Christian Vest Hansen ofrece opciones de JVM que ayudan mucho , pero no resuelven el problema por completo:

-XX:+UseConcMarkSweepGC
-XX:+CMSPermGenSweepingEnabled
-XX:+CMSClassUnloadingEnabled
-XX:MaxPermSize=128m
Peter Hilton
fuente

Respuestas:

5

Como ya se mencionó, probablemente esté experimentando fugas de cargadores de clases. Por alguna razón, tus clases no se están descargando. Esto puede suceder por dos razones.

  • Los objetos de dichas clases todavía existen en el montón, los objetos siempre hacen referencia a su clase, o
  • Se hace referencia al cargador de clases en alguna parte, por cualquier razón, los cargadores de clases hacen referencia a sus clases para no cargarlas dos veces

No hay una solución general para este problema. Una herramienta útil para ayudarlo a encontrar la causa raíz es la herramienta Eclipse Memory Analyzer , que puede aplicar a un volcado de montón desde su JVM (puede habilitar los volcados de montón en OOM con la opción -XX: + HeapDumpOnOutOfMemoryError). Quizás comience a buscar objetos java.lang.Class de su aplicación web para ver por qué se mantienen con vida. Desafortunadamente, PermGen normalmente no es parte de un volcado de montón JVM, por lo que solo puede intentar encontrar artefactos correlacionados en el resto del montón (los objetos de clase no se almacenan en PermGen si no estoy equivocado, solo el código de byte real es, por favor corrígeme si me equivoco).

HTH.

Editar:
Dave Cheney sugiere en un comentario que java.lang.Class-objects son de hecho parte de PermGen y no se incluyen en un volcado de montón de zona activa normal. A menos que tenga una JVM que escriba esta información en el volcado de almacenamiento dinámico, necesitará un enfoque diferente. Todavía puede buscar instancias de sus objetos, pero si está filtrando clases / cargadores de clases (desafortunadamente, ambos se implican entre sí) parece que necesita buscar otros signos (objetos de metadatos de JBoss, etc.).

falstro
fuente
1
Estoy bastante seguro de que los objetos de clase se almacenan en PermGen (es decir, objetos que son instancias de clase). Hay un área separada en Sun JVM llamada Code Cache, que es donde se almacena el código que se ha compilado en código máquina. Tanto PermGen como Code Cache son parte de la memoria Non Heap que puedes ver usando herramientas como jconsole
Dave Cheney
@ Dave Cheney: Tienes razón. Los objetos de clase filtrados atascados en PermGen suelen ser la causa del problema del OP.
Eddie
huevas, aunque no creo que el contenido de PermGen esté escrito en el volcado del montón (esto está usando Sun JVM, no tengo mucha experiencia con los demás), el formato de volcado hprof ciertamente sabe cosas como, cuántos se cargaron las clases, cuántos cargadores de clases, etc. Puede ver esto al abrir hprof en Eclipse Memory Analyzer). Lo que probablemente no está escrito son los grandes datos de clase binaria que componen el código de bytes de Java, lo que se ve en el volcado del montón es el 'trozo' de la instancia de Clase almacenada en PermGen.
Dave Cheney
2

La causa subyacente son las referencias a las clases que se han descartado que se filtran fuera de su cargador de clases, evitando que la JVM descargue esas clases de la generación permanente. Esas banderas que usa pueden hacer que la JVM purgue agresivamente las clases que no se pueden cargar, pero no resolverá el problema subyacente.

Hay una buena, abeit compleja explicación aquí

Dave Cheney
fuente
1

La causa del error PermGen OutOfMemory es la nueva implementación de la aplicación. La causa subyacente son los objetos de clase filtrados en PermGen de las redespliegues.

Por supuesto, la solución es reiniciar la JVM después de un cierto número de redespliegues.

Este es un problema muy difícil de resolver por completo, aunque con un poco de investigación a menudo puede hacer grandes mejoras. Aquí es donde comienza: cuando su aplicación web se detiene, asegúrese de que:

  • todos los hilos que comenzaste se detienen
  • todos los ThreadPools que comenzaste se cierran
  • se liberan todas las referencias estáticas que puede liberar

Estas son algunas de las cosas que pueden hacer que un objeto Class quede atrapado en PermGen.

Además, tenga en cuenta que no todas las JVM (o todas las versiones de JVM) tendrán objetos de clase GC en PermGen. Si está ejecutando una JVM o una versión de una JVM que no será un objeto de clase GC en PermGen, entonces su única opción es reiniciar la JVM después de un cierto número de redespliegues. Esto probablemente no se aplica a usted, teniendo en cuenta las opciones de JVM que mencionas.

Eddie
fuente