2011-06-20 19 views
10

Me pregunto si debo lidiar con los MBeans que están registrados directa o indirectamente desde mi aplicación que se implementa en un contenedor de servlets.JMX: ¿Cómo evitar las fugas de memoria de Classloader en un contenedor de servlets?

En la mayoría de los casos hay dos opciones para recuperar una MBeanServer que se puede utilizar para registrar

  • crear su propia MBeanServer usando MBeanServerFactory.createMBeanServer()

  • Uso ManagementFactory.getPlatformMBeanServer()

Al utilizar la primera opción, es fácil anular el registro de todos los MBeans: Jus t invocar MBeanServer.releaseMBeanServer(myMBeanServer).

Pero, ¿qué pasa con la segunda opción que se utiliza a menudo en muchas aplicaciones de terceros? (y por cierto, esta también es la forma recomendada de Sun/Oracle).

Como se utiliza la plataforma MBeanServer, no se cancelará el registro cuando se destruya el contexto del servlet, pero, lo que es peor, todavía contiene una referencia al cargador de clases de la aplicación web.
Como consecuencia, no se liberarán todas las referencias estáticas de la aplicación web, lo que provocará una fuga.

Si te gusta probar esto: Sólo desplegar una sencilla aplicación web que asigna una matriz de 100 MB que es referencias estática y que utiliza un controlador JDBC de Oracle (se registrará un MBean de diagnóstico utilizando el servidor mbean plataforma), desplegado en gato. Detenga la aplicación y reiníciela. Repita esto y verá OutOfMemoryError.

Preguntas:

  • ¿Tengo que hacer frente a estos problemas, en general, o se trata de un problema del contenedor de servlets y/o la biblioteca tercera parte?

  • ¿Hay una manera de conseguir todos los MBeans de un MBeanServer qué clases se cargan por una específica ClassLoader?

  • ¿Qué puedo hacer para evitar esto? ¿Debo hacer un seguimiento de todos los MBeans registrados en la plataforma MBeanServer y anular el registro durante contextDestroyed()?

+0

Tal vez echar un vistazo a http://stackoverflow.com/questions/386892/is-it-necessary-to-unregister-an-mbean-from-the-platform-mbean-server – nfechner

Respuesta

1

¿Qué puedo hacer para evitar esto? ¿Tengo tengo que realizar un seguimiento de todos los MBeans registrados a la plataforma MBeanServer y anular el registro durante contextDestroyed()?

Este ha sido mi consejo estándar. No estoy al tanto de una mejor opción.

0

Lo que está diciendo bkail. Además, si está utilizando un marco como Spring (vea MBeanExporter), debería deshacerse del registro de sus objetos JMX en Context Shutdown, lo que debería ocurrir como parte de la redistribución de la aplicación web.

3

Estoy usando un tercero tan malvado. Para garantizar el cierre adecuado del contexto de servlet, enumero los beans usando mbeanServer.queryMBeans(null, null) y luego unregisterMBean() los beans que están en el dominio de terceros.

Set<ObjectInstance> beans = mbeanServer.queryMBeans(null, null); 
for (ObjectInstance objectInstance : beans) { 
    if (objectInstance.getObjectName().getDomain().equals("third-party-domain")) { 
     try { 
      mbeanServer.unregisterMBean(objectInstance.getObjectName()); 
     } catch (MBeanRegistrationException exception) { 
      //error handling 
     } catch (InstanceNotFoundException exception) { 
      //error handling 
     } 
    } 
} 
+0

que había también solo elimine el registro de los MBeans cargados por el cargador de clases de la aplicación web: 'if (mbeanServer.getClassLoaderFor (objectInstance.getObjectName() == Thread.currentThread(). getContextClassLoader())' – John29

Cuestiones relacionadas