Tiré de cette belle tutoriel du soleil :
Motivation
Les applications écrites dans des langages de programmation à compilation statique, tels que C et C++, sont compilées en instructions natives, spécifiques à la machine, et enregistrées sous forme de fichier exécutable. Le processus de combinaison du code en un code natif exécutable est appelé liaison - la fusion du code compilé séparément avec le code de la bibliothèque partagée pour créer une application exécutable. Ce processus est différent dans les langages de programmation à compilation dynamique tels que Java. En Java, les fichiers .class générés par le compilateur Java restent tels quels jusqu'à ce qu'ils soient chargés dans la machine virtuelle Java (JVM) - en d'autres termes, le processus de liaison est effectué par la JVM au moment de l'exécution. Les classes sont chargées dans la JVM en fonction des besoins. Et lorsqu'une classe chargée dépend d'une autre classe, celle-ci est également chargée.
Lorsqu'une application Java est lancée, la première classe à s'exécuter (ou le point d'entrée dans l'application) est celle qui possède la méthode publique static void appelée main(). Cette classe comporte généralement des références à d'autres classes, et toutes les tentatives de chargement des classes référencées sont effectuées par le chargeur de classe.
Pour avoir une idée de ce chargement de classe récursif ainsi que de l'idée de chargement de classe en général, considérez la classe simple suivante :
public class HelloApp {
public static void main(String argv[]) {
System.out.println("Aloha! Hello and Bye");
}
}
Si vous exécutez cette classe en spécifiant l'option de ligne de commande -verbose:class, de façon à ce qu'elle affiche les classes qui sont chargées, vous obtiendrez une sortie qui ressemble à ce qui suit. Notez qu'il ne s'agit que d'une sortie partielle, la liste étant trop longue pour être affichée ici.
prmpt>java -verbose:class HelloApp
[Opened C:\Program Files\Java\jre1.5.0\lib\rt.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jsse.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\jce.jar]
[Opened C:\Program Files\Java\jre1.5.0\lib\charsets.jar]
[Loaded java.lang.Object from shared objects file]
[Loaded java.io.Serializable from shared objects file]
[Loaded java.lang.Comparable from shared objects file]
[Loaded java.lang.CharSequence from shared objects file]
[Loaded java.lang.String from shared objects file]
[Loaded java.lang.reflect.GenericDeclaration from shared objects file]
[Loaded java.lang.reflect.Type from shared objects file]
[Loaded java.lang.reflect.AnnotatedElement from shared objects file]
[Loaded java.lang.Class from shared objects file]
[Loaded java.lang.Cloneable from shared objects file]
[Loaded java.lang.ClassLoader from shared objects file]
[Loaded java.lang.System from shared objects file]
[Loaded java.lang.Throwable from shared objects file]
.
.
.
[Loaded java.security.BasicPermissionCollection from shared objects file]
[Loaded java.security.Principal from shared objects file]
[Loaded java.security.cert.Certificate from shared objects file]
[Loaded HelloApp from file:/C:/classes/]
Aloha! Hello and Bye
[Loaded java.lang.Shutdown from shared objects file]
[Loaded java.lang.Shutdown$Lock from shared objects file]
Comme vous pouvez le constater, les classes d'exécution Java requises par la classe d'application (HelloApp) sont chargées en premier.
Chargeurs de classe dans la plate-forme Java 2
Le langage de programmation Java ne cesse d'évoluer pour faciliter la vie des développeurs d'applications. Pour ce faire, il fournit des API qui vous simplifient la vie en vous permettant de vous concentrer sur la logique métier plutôt que sur les détails de mise en œuvre des mécanismes fondamentaux. Le passage récent de J2SE 1.5 à J2SE 5.0, afin de refléter la maturité de la plate-forme Java, en est la preuve.
Depuis le JDK 1.2, un chargeur de classes d'amorçage intégré à la JVM est chargé de charger les classes du runtime Java. Ce chargeur de classes ne charge que les classes qui se trouvent dans le classpath de démarrage, et comme il s'agit de classes de confiance, le processus de validation n'est pas effectué comme pour les classes non fiables. En plus du chargeur de classes d'amorçage, la JVM possède un chargeur de classes d'extension responsable du chargement des classes provenant des API d'extension standard, et un chargeur de classes système qui charge les classes provenant d'un chemin de classes général ainsi que les classes de votre application.
Comme il y a plus d'un chargeur de classe, ils sont représentés dans un arbre dont la racine est le chargeur de classe d'amorçage. Chaque chargeur de classe a une référence à son chargeur de classe parent. Lorsqu'on demande à un chargeur de classe de charger une classe, il consulte son chargeur de classe parent avant de tenter de charger l'élément lui-même. Le parent consulte à son tour son parent, et ainsi de suite. Ce n'est donc qu'après que tous les chargeurs de classe ancêtres n'aient pas trouvé la classe que le chargeur de classe actuel intervient. En d'autres termes, on utilise un modèle de délégation.
La classe java.lang.ClassLoader
Le site java.lang.ClassLoader
est une classe abstraite qui peut être sous-classée par des applications qui ont besoin d'étendre la manière dont la JVM charge dynamiquement les classes. Les constructeurs de java.lang.ClassLoader
(et ses sous-classes) vous permettent de spécifier un parent lorsque vous instanciez un nouveau chargeur de classe. Si vous ne spécifiez pas explicitement un parent, le chargeur de classes du système de la machine virtuelle sera attribué comme parent par défaut. En d'autres termes, la classe ClassLoader utilise un modèle de délégation pour rechercher des classes et des ressources. Par conséquent, chaque instance de ClassLoader est associée à un chargeur de classe parent, de sorte que lorsqu'il est demandé de trouver une classe ou des ressources, la tâche est déléguée à son chargeur de classe parent avant de tenter de trouver la classe ou la ressource elle-même. Le site loadClass()
de la méthode ClassLoader effectue les tâches suivantes, dans l'ordre, lorsqu'elle est appelée pour charger une classe :
Si une classe a déjà été chargée, elle la retourne. Sinon, il délègue la recherche de la nouvelle classe au chargeur de classe parent. Si le chargeur de classe parent ne trouve pas la classe, loadClass()
appelle la méthode findClass()
pour trouver et charger la classe. Le site finalClass()
recherche la classe dans le chargeur de classes actuel si la classe n'a pas été trouvée par le chargeur de classes parent.
Vous trouverez plus d'informations dans l'article original, qui vous montre également comment mettre en œuvre vos propres chargeurs de classe réseau, ce qui répond à votre question du pourquoi (et du comment). Voir aussi le Documents de l'API .
0 votes
Vous obtiendrez de meilleurs résultats si vous précisez votre question, par exemple en indiquant une partie spécifique que vous ne comprenez pas, le lien avec une autre langue que vous connaissez, etc.
77 votes
Il s'agit d'une question tout à fait raisonnable, si l'on se place du point de vue de quelqu'un qui cherche quelques phrases simples pour expliquer le concept
1 votes
Cette vidéo pourrait vous intéresser : Vous avez vraiment des chargeurs de classe ?