Le classpath

Le contenu de cet article est principalement issu de la présentation Le classpath n’est pas mort, mais presque de Alexis Hassler à Devoxx France 2013.

Pour commencer, il existe deux types de classes :

  • classes du JRE (String, Integer par exemple)
  • classes provenant de librairies externes ou du code de l’application

Une classe est identifiée par son nom et par son classloader. Pour toutes les classes n’étant pas dans le JRE, il faut indiquer au lancement de l’application le classpath à utiliser. Si le classpath est erroné deux exceptions peuvent être levées : NoClassDefFoundError et ClassNotFoundException.

Qu’est ce qu’un classloader

Un classloader est avant tout une classe qui est capable de charger une autre classe ou des ressources (properties, xml, images …)

Lorsque le runtime java a besoin de charger une nouvelle classe pour une application, il la recherche dans l’ordre suivant :

  1. Bootstrap classes via le bootstrap classloader : le cœur de la JRE (rt.jar), l’internationalisation (i18n.jar) et bien d’autres
  2. Installed extensions via l’extension classloader : classes présentes dans le dossier lib/ext de la JRE. A ne pas confondre avec le mécanisme d’endorced.
  3. System classes via le system classloader : classes de l’application ainsi que de ses librairies

Tous les classloader (sauf le bootstrap) possède un parent.
Pour connaitre le classloader d’une classe :

MaClasse.class.getClassLoader() // sun.misc.Launcher$AppClassLoader
String.class.getClassLoader() // null

Le classloader des classes du JRE (bootstrap classloader) n’est pas un composant java. Si le bootstrap classloader était un objet Java, il lui faudrait un classloader à qui il faudrait également un classloader …
Le bootstrap classloader est donc un bout de code natif.

Délégation

Un classloader est faignant, c’est à dire que lorsqu’on lui demande de charger une classe, il demande à son parent de la charger à sa place. Il la chargera si ses parents ne l’ont pas trouvé. Le modèle de délégation est « parent first »

Manipuler le classpath

Positionner le classpath

  • system classloader :  java -cp mon_jar.jar
  • extension classloader : java -Djava.ext.dirs=dossier_de_mon_jar
  • bootstrap classloader :
    • java -Xbootclasspath:mon_jar.jar => liste des jar gérés par le bootstrap
    • java -Xbootclasspath/a:mon_jar.jar append
    • java -Xbootclasspath/p:mon_jar.jar prepend

Lire le classpath

  • system classloader : System.getProperty(« sun.class.path »)
  • extension classloader : System.getProperty(« java.ext.dirs »)
  • bootstrap classloader : System.getProperty(« sun.boot.class.path »)

 Créer son propre classloader

Il est possible de créer son propre classloader. Les serveurs d’application, jrebel javassist, cglib et bien d’autres se servent de cette possibilité. Par exemple, dans Tomcat, chaque WAR a son propre classloader. A cela s’ajoute un classloader commun qui gère le dossier lib de Tomcat.

      Bootstrap
          |
       System
          |
       Common
       /     \
  Webapp1   Webapp2 ...

Le web application classloader de Tomcat diverge du modèle de délégation « parent first » car avant de passer la main à son parent, il va chercher la classe dans le WAR. Il est « local first ».

Liens

http://docs.oracle.com/javase/tutorial/ext/basics/load.html
http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html

Laisser un commentaire


− quatre = 2


NOTE - Vous pouvez utiliser les éléments et attributs HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>