¿Hay alguna forma de evitar las fugas de memoria de subempleo en Tomcat?


Esta pregunta es para cualquiera que haya probado el botón "Buscar fugas" en el administrador de Tomcat y haya obtenido algunos resultados como estos:

Las siguientes aplicaciones web fueron detenidas (recargadas, no desplegadas), pero sus clases de ejecuciones anteriores todavía se cargan en memoria, lo que causa una fuga de memoria (use un generador de perfiles para confirmar):
/ leaky-app-name

Asumo que esto tiene algo que ver con ese error de "Perm Gen space" que a menudo obtienes con frequent redistribuciones.

Así que lo que estoy viendo en jconsole cuando despliegue es que mis clases cargadas van de aproximadamente 2k a 5k. Entonces usted pensaría que un subempleo debería volver a bajarlas a 2k pero permanecen en 5k.

También he intentado usar las siguientes opciones de JVM:

-XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC -XX:+CMSPermGenSweepingEnabled

Vi bajadas MUY menores en la cantidad de espacio de generación Perm utilizado, pero no lo que esperaba y los recuentos de clases cargadas no cayeron.

Así que hay una manera de configurar Tomcat o diseñar su aplicación para descargar mejor en un subempleo? ¿O estamos atascados con reiniciar el servidor después de algunas sesiones de depuración importantes?

Salida de la versión Tomcat:

Versión del servidor: Apache Tomcat / 6.0.29
Servidor construido: julio 19 2010 1458
Número de servidor: 6.0.0.29
Nombre del sistema operativo: Windows 7
Versión del sistema operativo: 6.1
Arquitectura: x86
JVM Version: 1.6.0_18-b07
Proveedor de JVM: Sun Microsystems Inc.

Actualización:

Gracias a la respuesta de celias, decidí investigar un poco más y creo que determiné que el culpable estaba en mi aplicación gracias a CXF, Spring y JAXB.

Después de aprender a perfilar una aplicación Java, apunté al generador de perfiles a Tomcat y tomé algunos volcados e instantáneas para ver cómo se veían los objetos y las clases en la memoria. Descubrí que algunas de las enumeraciones de mi esquema XML utilizado en mi CXF / JAXB (wsdl2java) las clases generadas persistían después de un subempleo. Según mi vertedero parece que los objetos estaban atados a un Mapa. Descargo de responsabilidad: Admito que todavía estoy un poco verde con el perfil y el rastreo del árbol de llamadas de un objeto puede ser un desafío en Java.

También debo mencionar que ni siquiera invoco el servicio, solo desplegado y luego no desplegado. Los objetos en sí mismos parecían cargarse a través de la reflexión iniciada a partir de la primavera en el despliegue. Creo que seguí la convención para configuración de un servicio CXF en primavera. Así que no estoy 100% seguro si esto es culpa de Spring/CXF, JAXB o reflection.

Como nota al margen: la aplicación en cuestión es un servicio web que utiliza Spring/CXF y el XML resulta ser un esquema bastante complejo (una extensión de NIEM).

Author: waltwood, 2010-12-30

2 answers

Si desea asegurarse de no causar fugas, debe hacer lo siguiente:

  • Asegúrese de que su aplicación web no utiliza ninguna clase java que esté en las bibliotecas compartidas del contenedor web. Si tiene bibliotecas compartidas, asegúrese de que no haya referencias sólidas a los objetos en esas bibliotecas
  • Evite el uso de variables estáticas, especialmente en objetos java como HashTable, Sets, etc. Si es necesario, asegúrese de llamar a remove para liberar los objetos con los mapas, lista...

Aquí también hay un buen artículo sobre ThreadLocal y MemoryLeaks - http://blog.arendsen.net/index.php/2005/02/22/threadlocals-and-memory-leaks-revisited /

 15
Author: celias,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-19 22:24:45

Se supone que Tomcat 7 traerá mejoras en esta área. Ver Características de Apache Tomcat 7, sección titulada No Más Fugas!

Creen que ahora pueden hacer frente a una gran cantidad de fugas de memoria causadas por las aplicaciones web. Desafortunadamente, todavía está en beta.

Aparte de eso, solo puedo decir que he hecho la misma experiencia y no he encontrado una solución. La implementación generalmente requiere reiniciar Tomcat después. No tengo idea de quién es el culpable: mi web aplicación, Tomcat, Hibernación, Tapiz o varios de ellos.

 6
Author: Codo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-12-30 18:32:24