Devoxx France 2014 – Do you really get classloaders

Cette première conférence de vendredi, présentée par Oleg Selajev, nous a plongé dans les principes de base de chargement des classes dans une application.

Pour commencer, Oleg a précisé ce qu'était un "classloader" : il s'agit d'une implémentation de la classe abstraite ClassLoader.

Lors du chargement d'une classe, chaque ClassLoader délègue la recherche de cette classe à son ClassLoader parent, jusqu'à celui de plus haut niveau appelé "bootstrap class loader", créé au démarrage de la JVM...
Sauf dans le cas de modules JEE où la résolution s'effectue dans l'autre sens (war -> ear -> container par exemple).

Cette résolution est utilisée lors de chaque instanciation de classe :

public class A {
     B b = new B();
}

est transformé en :

public class A {
     B b = A.class.getClassLoader().loadClass("B");
}

Oleg a ensuite présenté les erreurs qu'ont déjà rencontré tous les développeurs, liées aux problématiques de chargement des classes par plusieurs ClassLoaders.
Par exemple :

  • NoClassDefFoundError : la classe cherchée n'est pas connue du ClassLoader qui exécute le programme. Une piste d'étude est l'appel à la méthode getURLs() du ClassLoader, pour voir les jar présent dans le classpath à l'exécution.
  • NoSuchMethodError : la version de la classe entre la compilation et l'exécution est différente. L'utilisation de l'outil javap permet d'obtenir des informations sur la classe contenant la méthode recherchée ; ainsi que la méthode getResource("path.to.MyClass") pour voir ce qui est présent dans le classpath.
  • ClassCastException : MyClass cannot be cast to MyClass : peut-être le message d'erreur le plus bizarre rencontré ! Mais la raison est simple : la classe fournie par le serveur est différente de celle fournie par l'environnement, car elle n'est pas servie par le même ClassLoader (dans ce contexte, le nom complet d'une classe est construit avec le ClassLoader qui la fournit, en plus de son chemin dans les packages).
  • Ainsi que d'autres erreurs aux causes similaires : LinkageError et IllegalAccessError (des classes qui sont bien dans le même package, mais chargées par des ClassLoader différents).

La cause commune de ces problèmes, pour les développeurs, est la différence entre l'environnement de compilation et l'environnement d'exécution. Suite à une question d'un auditeur, Oleg a indiqué ne pas connaître d'outils qui permettrait de détecter ces erreurs dès l'écriture du code, mais a conseillé l'utilisation de JRebel pour analyser et debugger l'environnement d'exécution.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.