JMX pour les nuls... - Chargement dynamique de MBeans - Partie 6

left

Cet article toujours dans la lignée de ma petite série d’articles sur JMX (cf. introduction, partie 1 portant sur les généralités, partie 2 portant sur les différents MBeans et le concept de Notification, partie 3 sur les agents JMX, partie 4 sur les classes de base et partie 5 sur le MBeanServer) sera plus accès sur les capacités de chargement dynamique des MBeans. Cependant, il n’abordera que succinctement cette partie car il est nécessaire d’avoir une très bonne connaissance du fonctionnement du classloader et qu’un simple article ne saurait l’aborder comme il se doit.

Table des matières

Chargement dynamique des MBeans

JMX propose un service de chargement dynamique de MBeans qui s’appuie sur les fonctionnalités du classloader Java pour récupérer et instancier les MBeans qui peuvent utilisés indifféremment des classes Java ou des librairies natives. Cette fonctionnalité existe car lorsque le serveur JMX est démarré, il peut ne pas avoir connaissance de tous les MBeans et devoir en télécharger. Pour ce faire, un service particulier chargé de gérer des applets de management (m-let) est utilisé pour instancier les MBeans obtenus d’une URL distante sur le réseau. En fait, le service de m-let permet d’instancier et d’enregistrer des MBeans dans le MBean Server en chargeant un fichier texte, dont la localisation est spécifiée par une URL, qui contient les informations des MBeans à obtenir. Quand ce fichier texte est chargé, toutes les classes spécifiés par le tag MLET sont téléchargées et une instance de chaque MBean spécifié est crée et enregistré. Le service de m-let étant lui-même un MBean enregistré dans le MBean Server, il peut être utilisé par d’autres MBeans, par d’autres applications ou par d’autres applications d’administration et de supervision distantes.

medium

Depuis Java 5, toute application Java possède un MBean Server qui peut être obtenu via la méthode java.lang.management.ManagementFactory.getPlatformMBeanServer()

medium

La classe MLet étend la classe URLClassLoader, ce qui implique qu'il s'agit également d'un classe loader.

Dans le cas générique, l'appel à la méthode getMBeansFromURL() du service de m-let permet de :
  • télécharger le fichier texte contenant le descriptif des MBeans (un MBean par tag MLET),
  • télécharger les classes nécessaires,
  • charger les classes dans le classe loader du MBean Server,
  • instancier les MBeans,
  • enregistrer les MBeans instanciés préalablement,
  • renvoyer les instances des MBeans.

Dans le cas où le MBean contient de méthodes natives et que des librairies natives sont chargées en utilisant la méthode System.loadLibrary, alors la méthode findLibrary du classe loader du m-let est appelé pour trouver la librairie. Cette méthode surcharge celle de la classe ClassLoader et, si la librairie est trouvée, copie cette dernière à l'emplacement retourné par la méthode getLibraryDirectory de la classe MLet.

Le MBean Server maintient une liste de classe loader dans le repository de classe loader (aussi appelé default loader Repository).
Ce classe loader Repository est utilisé dans les méthodes createMBean et instantiate de l'interface MBean Server : le repository loader repository est utilisé pour trouver et charger les classes.
Si un m-let ne trouve pas les classe à l'URL, il essaie de chargeer les classes du classe loader repository.

Dans le cas où plusieurs MBean Server sont présent dans une même JVM, ils disposent chacun de leurs propres classe loader repository qui sont indépendants les uns des autres.

L'ordre des classes loader dans le repository est important : quand une classe est chargée dans le repository, chaque classe loader est interrogé pour charger la classe. Si un loader réussi à charger la classe alors la recherche s'arrête, sinon (s'il lève une exception ClassNotFoundException) la recherche continue jusqu'à ce qu'il n'y en ait plus (dans ce cas l'exception ClassNotFoundException est levée).
Le premier loader dans la classe loader repository est celui qui a chargé l'implémentation du MBean Server. Se trouve ensuite les loaders des MBeans, l'ordre des loaders étant celui du chargement des MBeans.
Ainsi, on aura, par exemple :
Un MBean m1 apparait avant le MBean m2 si la méthode createMBean ou registerMBean qui a enregistrée m1 s'est terminé avant le démarrage de l'opération qui a enregistré m2. Si la méthode d'enregistrement de m2 a démarré avant la fin de la méthode d'enregistrement de m1, alors l'ordre des loaders est indéterminé.

Un m-let est un classe loader et, comme l'indique le comportement d'un classe loader standard, il charge une classe en utilisant la méthode loadClass :
En premier lieu, il envoie une requête au classe loader parent pour charger la classe (le classe loader parent est celui spécifié lors le m-let est créé (par défaut le classe loader système)), puis, dans un second temps, si le classe loader parent n'a pas pu charger la classe, le m-let tente de la charger dans sa liste d'URL. Enfin, si ces deux essais se soldent par un échec, le m-let tente de charger la classe dans le classe loader repository (dans ce cas, il est dit qu'il délègue au classe loader repository).
Si ces trois tentatives échouent, l'exception ClassNotFoundException est levée.

Pour avoir d'autres informations sur le chargement de classe ainsi que sur les problèmes qui peuvent apparaitre, voir les chapitres 8.4 The Class Loader Repository et 8.5 Using the Correct Class Loader for Parameters des spécifications JMX.

 Share!

 
comments powered by Disqus