2010-06-02 10 views
10

En casi todos los grandes proyectos de Java en los que he estado involucrado, he notado que la calidad del servicio de la aplicación se degrada con el tiempo de actividad del contenedor. Probablemente esto se deba a fugas de memoria en el código.¿Práctica recomendada para manejar fugas de memoria en grandes proyectos de Java?

La forma correcta de resolver este problema es, obviamente, rastrear la causa raíz del problema y corregir las fugas en el código. La forma rápida y sucia de resolver el problema es simplemente reiniciar Tomcat (o el contenedor de servlets que esté utilizando).

Estas son mis tres preguntas:

  • Suponga que usted elija para resolver el problema mediante el trazado de la causa raíz del problema (las pérdidas de memoria), ¿cómo recoger los datos para hacer un zoom sobre el problema ?

  • Supongamos que elige la forma rápida y sucia de acelerar las cosas simplemente reiniciando el contenedor, ¿cómo reuniría los datos para elegir el ciclo de reinicio óptimo?

  • ¿Ha podido implementar y ejecutar proyectos durante un período de tiempo prolongado sin tener que reiniciar el contenedor de servlets para recuperar la elegancia? ¿O un servlet ocasional reinicia algo que uno simplemente tiene que aceptar?

Respuesta

9

Supongamos que decide resolver el problema rastreando la causa raíz del problema (la pérdida de memoria), ¿cómo reuniría datos para acercar el problema?

Realice un volcado de pila utilizando jmap y cargue el volcado con Eclipse Memory Analyzer. Desde allí puede analizar qué objetos están consumiendo la mayor cantidad de memoria, qué "raíces" están impidiendo la recolección de otros objetos, etc.

Existen otros programas de análisis de pila, como jhat, pero encontré EMA en ser la solución más rápida y mejor (gratis).

Supongamos que elige la forma rápida y sucia de acelerar las cosas simplemente reiniciando el contenedor, ¿cómo reuniría los datos para elegir el ciclo de reinicio óptimo?

Utilice JMX para controlar el tamaño del almacenamiento dinámico y otras estadísticas de montón y de GC.

¿Ha podido implementar y ejecutar proyectos durante un período de tiempo prolongado sin tener que reiniciar el contenedor de servlets para recuperar la elegancia?

Sí. Evitando/reparando fugas de memoria.

+1

+1 para la respuesta sencilla y sin sentido. Reiniciar el contenedor es una solución simple, pero no una solución a largo plazo. Automatizar el reinicio del contenedor es una solución automática, que tiene algunos de los beneficios de una solución, pero también tiene muchos inconvenientes. –

1

Idealmente, no debería necesitar reiniciar su programa o servlet.

Mi experiencia es que la mayoría de las causas de los problemas de memoria suelen ser el resultado de un problema en la asignación o puesta en común de un pequeño conjunto de clases.

Una herramienta como VisualVM es ideal para eso, ya que puede averiguar dónde se encuentra la peor parte de su asignación de objetos.

Probablemente sea un poco más complicado con Tomcat ya que también controlará el marco de trabajo, pero con suficiente cuidado y paciencia a menudo puede identificar puntos de acceso en su lógica.

2

Existen algunas excelentes herramientas de creación de perfiles. Aprenda a usar uno regularmente y entienda la salida de asignación de memoria.

Básicamente sigue este proceso para cada función importante de su aplicación:

  • carrera a través del proceso una vez
  • GC dos veces
  • Marcar sus recuentos actuales de asignación para todos los objetos
  • carrera a través de su procesar nuevamente
  • GC dos veces
  • Marcar nuevamente
  • Diff las dos marcas

Si no están muy cerca, es probable que tenga una fuga.

Si cualquier recuento de objetos crece en una cantidad determinada cada iteración de este proceso, entonces definitivamente tiene una fuga.

Cuestiones relacionadas