Chargement dynamique de classes - INFORMATIQUE
Transcript of Chargement dynamique de classes - INFORMATIQUE
![Page 1: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/1.jpg)
Chargement dynamique de classes
Philippe Collet
A partir des éléments de cours de Michel Buffa
Master 1 IFI 2014-‐2015
h1p://dep6nfo.unice.fr/twiki/bin/view/Minfo/GenieLog1415
P. Collet 1
![Page 2: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/2.jpg)
Plan
• Principe du ClassLoader • Ecrire un ClassLoader custom • Architecture pour charger des plugins • Comment recharger des plugins • Application au simulateur de bébêtes
P. Collet 2
![Page 3: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/3.jpg)
Définition d ’un ClassLoader
• La JVM contient un ClassLoader
• Les Class Loaders permettent de charger des classes depuis le filesystem, mais aussi depuis de multiples endroits (BD, réseau, etc…)
• Rôle : convertir un nom de classe en tableau d ’octets représentant la classe Class c = loadClass(String nomClasse, boolean
resolveIt); P. Collet 3
![Page 4: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/4.jpg)
Généralités sur les ClassLoaders
• Toutes les JVM ont un ClassLoader (il peut charger certaines classes sans vérifications, JDK…)
• Le CL par défaut implémente une méthode loadClass() qui cherche dans le CLASSPATH, les fichiers .jar et/ou .zip
• On peut créer de nouveaux CL en dérivant de la classe ClassLoader et en redéfinissant loadClass() et les méthodes qu’elle utilise (findClassFromClass, ResolveClass…)
P. Collet 4
![Page 5: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/5.jpg)
Moment de chargement des classes
• Ca dépend !
• En général quand : – Toto t = new Toto(); – Référence statique comme :
• System.out, • Toto.class, • forName("Toto");
P. Collet 5
![Page 6: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/6.jpg)
Ecrire son propre ClassLoader ?
• Intérêt ? – Charger des classes depuis le WWW, – Charger des classes depuis une BD, – Charger des classes « différemment »
• Ne Marche pas avec les applets ! • Depuis JDK1.2, un URLClassLoader est
disponible
P. Collet 6
![Page 7: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/7.jpg)
Ecrire un ClassLoader : les étapes
• Sous-classer ClassLoader et implémenter la méthode abstraite loadClass – 1) Vérifier le nom de la classe, voir si on ne l’a pas déjà chargée – 2) Vérifier s’il s’agit d’une classe « Système »
– 3) Essayer de la charger
– 4) Définir la classe pour la VM – 5) La résoudre (charger les dépendances)
– 6) Renvoyer la classe à l’appelant
• JDK1.3 et plus: sous-classer SecureClassLoader si on veut respecter les recommandations relatives à la nouvelle politique de sécurité de Java
P. Collet 7
![Page 8: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/8.jpg)
Exemple de ClassLoader custom public synchronized Class loadClass(String className, boolean resolveIt) throws
ClassNotFoundException { Class result;
Byte []classData; // 1) Cherche dans le cache si la classe n’a pas déjà été chargée result = (Class) classes.get(className);
if(result != null) return result;
// 2) Utilisation du primordial CL pour voir s’il s’agit d’une classe // Systeme. Très important de faire ce test ! Sinon on pourrait remplacer // Le security manager ! try { result = super.findSystemClass(className); return result; } catch(ClassNotFoundException e) { System.out.println("Pas une classe système !");
}
// 3) On charge la classe depuis NOTRE REPOSITORY (le www ou une BD par exemple). Méthode à nous ! Voir exemple page suivante classData = getImplFromDataBase(className); if(classData == null) { throw new ClassNotFOundException() }
P. Collet 8
![Page 9: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/9.jpg)
Exemple de ClassLoader custom (suite)
... // 4) On "définit" la classe (on la parse). En fait, la méthode suivante va // vérifier la validité du ByteCode + voir si tout est ok. // Stocke le tout dans la JVM dans une certaine structure de données.
result = defineClass(classData, 0, classData.length);
// 5) "Résoudre" la classe. C'est-à-dire faire le même traitement que celui qui est en train d'être fait, mais pour les superclasses et les classes dépendantes. if(resolveIt) resolveClass(result);
// Avant de renvoyer le résultat final, on met la classe dans le cache classes.put(className, result);
// 6) On renvoie le résultat ! Return result;
}
P. Collet 9
![Page 10: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/10.jpg)
Exemple de code qui lit une classe
...
byte [] result;
try {
FIS fis = new FIS("store\\ " + className + ".impl");
result = new byte[fis.available()];
fis.read(result);
} catch(Exception e) {
return null;
}
P. Collet 10
![Page 11: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/11.jpg)
Exemple de code qui lit une classe depuis le WWW
...
URL url = new URL(urlClassName); URLConnection uc = new URLConnection(url);
int length = uc.getContentLength();
IS is = uc.getInputStream();
byte []data = new byte[length];
is.read(data); is.close();
return data;
...
P. Collet 11
![Page 12: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/12.jpg)
Utilisation d'un ClassLoader custom
Class c = ccl.loadClass("Toto"); Object o = c.newInstance();
((Toto) o).f();
• ne marche pas car seul le nouveau cl connaît Toto !
P. Collet 12
System ClassLoader
ccl ((Toto)o)
Class Toto
![Page 13: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/13.jpg)
Nécessité d'une Interface • Seul le nouveau CL connaît Toto, si on veut effectuer un cast, il faut
définir une Interface en commun, qui elle, est connue aussi du CL par défaut !
• Par exemple Plugin connue par le CL par défaut (SystemClassLoader par exemple), qui est implémentée par les classes chargées.
P. Collet 13
System ClassLoader
ccl
Class Toto
Interface MonPlugin
Class chargée dans le classpath
((MonPlugin)o)
![Page 14: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/14.jpg)
Ecrire des plugins • Truc simple : lire des plugins dans un répertoire • Définir une interface d'utilisation pour les plugins
• Chaque plugin devra implémenter cette interface • Chaque classe sera donc un Plugin
• Il suffit ensuite de – 1) Lire le contenu du répertoire – 2) Pour chaque nom de classe présent dans le répertoire "plugins"
• Class c = Class.forName(nomClasse); • Plugin p = (PluginDessin) c.newInstance(); • p.dessine(); // méthode présente dans Plugin.java
P. Collet 14
![Page 15: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/15.jpg)
Plugins suite...
• Difficultés lorsque – Pas de constructeur par défaut – Les plugins sont dans un .jar ou une BD
• Chercher des ressources ? Images, sons, etc…
• Class.forName(nomCLasse) est l'équivalent du loadClass(nomCLasse) étudié dans le cas d'un ClassLoader custom !
• Les plugins, il y en a partout !!! – Photoshop, IE, Firefox, Chrome…
P. Collet 15
![Page 16: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/16.jpg)
Plugins : modèle idéal
• Modèle idéal = un répertoire plugins, • Des fichiers .jar dans le répertoire,
• L’application « découvre » les jars et « absorbe » les plugins qu’ils contiennent.
• Chaque jar contient – la classe qui implémente l’interface Plugin.java, – les autres classes dont elle a besoin, – Les images, icônes, sons, docs, etc… dont le plugin a besoin…
P. Collet 16
![Page 17: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/17.jpg)
Plugin : modèle idéal • Mais problème lorsqu’il y a de trop nombreuses classes dans le
plugin… comment tester qu’une classe est réellement un plugin sans essayer de la charger, ce qui prend du temps… – Class.forName() est long… – Class.newInstance() aussi…
• Eclipse, par exemple, contient 800 plugins qui sont chargés au démarrage…
• Certains plugins étendent d’autres plugins et donc en dépendent, • L’ordre de chargement est important…
P. Collet 17
![Page 18: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/18.jpg)
Comment gérer ses plugins ?
• La solution passe souvent par un descripteur, une « carte » des plugins – Eclipse suit une norme pour décrire les plugins, leurs
dépendances, etc… Il utilise un descripteur XML
• Le problème No 1 avec les plugins est le temps de chargement…
• Mais les avantages sont nombreux…
P. Collet 18
![Page 19: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/19.jpg)
Développer un programme extensible par plugins
• Il faut fournir un SDK pour le développeur de plugins – Pour qu’il puisse compiler et tester ses plugins sans
avoir le code de l’application principale, – Il faut fournir : Classes et Interfaces nécessaires, – Un ou plusieurs plugins d’exemples, avec le fichier ant
correspondant, – De la doc, un tutorial, etc…
P. Collet 19
![Page 20: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/20.jpg)
Changer les plugins sans relancer le programme principal
• Principe des serveurs de Servlets/Jsps : on ajoute des classes mais on ne relance pas le programme…
• Exemple – Serveurs d’application en Java – On ne l’arrête jamais… – On dépose des plugins et ils sont « découverts » à
chaud…
P. Collet 20
![Page 21: Chargement dynamique de classes - INFORMATIQUE](https://reader031.fdocuments.net/reader031/viewer/2022012021/61689f1ed394e9041f713ad0/html5/thumbnails/21.jpg)
(Re-)Chargement à chaud
• Principe : changer le class Loader à chaque chargement de plugin… – Chaque class loader gère un « cache » des classes, si
on re-instancie le class loader, on peut charger/recharger des plugins à chaud…
– On utilisera un URLClassLoader pour ça…
– Il suffit de re-scanner toutes les 5 secondes par exemple le répertoire qui contient les plugins… ou bien à la demande (clic sur un bouton)…
P. Collet 21