JMX: Comment prévenir les memory leaks dans Classloader dans un conteneur de servlets?

Je me demande si et comment je devrais traiter les MBeans qui sont inscrits directement ou indirectement à partir de mon application déployée sur un conteneur de servlets.

Dans la plupart des cas, il existe deux options pour récupérer un MBeanServer que vous pouvez utiliser pour vous inscrire.

Lorsque vous utilisez la première option, il est facile de désenregistrer tous les MBeans: MBeanServer.releaseMBeanServer(myMBeanServer) simplement MBeanServer.releaseMBeanServer(myMBeanServer) .

Mais qu’en est-il de la deuxième option qui est souvent utilisée dans de nombreuses applications tierces? (et BTW, c’est aussi la méthode recommandée par Sun / Oracle).

Étant donné que la plate-forme MBeanServer est utilisée, elle ne sera pas désenregistrée lorsque le contexte du servlet sera détruit – mais pire encore, elle contiendra toujours une référence au chargeur de classe de l’application Web.
En conséquence, toutes les références statiques de l’application Web ne seront pas publiées, ce qui entraînerait une fuite.

Si vous souhaitez tester ceci: Déployez simplement une application Web simple qui alloue un tableau de 100 Mo référencé de manière statique et qui utilise un pilote oracle jdbc (il enregistre un MBean de diagnostic à l’aide du serveur mbean de la plateforme), déployé sur tomcat. Arrêtez l’application et redémarrez-la, répétez-la et vous obtiendrez une OutOfMemoryError .

Des questions:

  • Dois-je régler ces problèmes en général ou s’agit-il d’un conteneur de servlets et / ou d’une bibliothèque tierce?

  • Existe-t-il un moyen d’obtenir tous les MBeans d’un MBeanServer dont les classes sont chargées par un ClassLoader spécifique?

  • Que puis-je faire pour empêcher cela? Dois-je suivre tous les MBeans enregistrés sur la plate-forme MBeanServer et annuler son enregistrement pendant contextDestroyed() ?

Que puis-je faire pour empêcher cela? Dois-je suivre tous les MBeans enregistrés sur la plate-forme MBeanServer et annuler son enregistrement pendant contextDestroyed ()?

Cela a été mon conseil standard. Je ne suis pas au courant d’une meilleure option.

J’utilise un tel tiers malfaisant. Pour assurer la fermeture correcte du contexte de servlet, mbeanServer.queryMBeans(null, null) les beans à l’aide de mbeanServer.queryMBeans(null, null) puis d’ mbeanServer.queryMBeans(null, null) les beans mbeanServer.queryMBeans(null, null) dans le domaine du tiers.

 Set 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 } } } 

Qu’est-ce que bkail dit. De même, si vous utilisez une structure telle que Spring (voir MBeanExporter), elle devrait s’assurer de la désenregistrement de vos objects JMX lors de l’arrêt du contexte, ce qui devrait se faire dans le cadre du redéploiement de la Webapp.