Nous savons que nous pouvons remplacer le système classloader avec:
Java -Djava.system.class.loader=com.test.MyClassLoader xxx
Puis, depuis com.test.MyClassLoader
elle-même est une classe, par qui est-elle chargée?
Comment obtenir le fichier de classe de ce chargeur de classe "meta"?
Du Javadoc pour ClassLoader.getSystemClassLoader
:
Si la propriété système "Java.system.class.loader" est définie lorsque cette méthode est invoquée pour la première fois, la valeur de cette propriété est considérée comme étant le nom d'une classe qui sera renvoyée en tant que chargeur de classe système. La classe est chargée à l'aide du chargeur de classe système par défaut et doit définir un constructeur public qui accepte un seul paramètre de type ClassLoader qui est utilisé comme parent de délégation.
Le chargeur de classe système par défaut lui-même est spécifique à l'implémentation JVM.
Bootstrap classloader
est le parent de tous les classloaders
et charge les classes JDK standard dans le répertoire lib de JRE (rt.jar et i18n.jar). Toutes les classes Java. * Sont chargées par ce classloader
.
Extensions Classloader
est l'enfant immédiat de Bootstrap classloader. Ce classloader charge les classes dans le répertoire lib\ext du JRE.
System-Classpath classloader
est l'enfant immédiat du chargeur de classe Extensions. Il charge les classes et les jars spécifiés par la variable d'environnement CLASSPATH
Vous pouvez essayer d'injecter votre chargeur de classe personnalisé au moyen de la propriété "Java.system.class.loader" (voir ClassLoader # getSystemClassLoader ).
Default System class loader
est le parent des instances MyClassLoader,
§ ..la valeur de cette propriété est considérée comme le nom d'une classe qui sera retournée comme chargeur de classe système. La classe est chargée à l'aide du chargeur de classe système par défaut ..
..Ainsi, si votre chargeur de classe remplace X comme chargeur de classe système, le parent de votre chargeur de classe sera X, le chargeur de classe système par défaut.
(X est d'un type comme Sun.misc.Launcher$AppClassLoader
.)
Plus d'informations peuvent être trouvées sur docs.Oracle.com - Comment le Java Launcher Finds Classes :
Le lanceur Java, Java, lance la machine virtuelle Java. La machine virtuelle recherche et charge les classes dans cet ordre:
Classes d'amorçage - Classes qui comprennent la plate-forme Java, y compris les classes dans rt.jar et plusieurs autres fichiers jar importants .
Classes d'extension - Classes qui utilisent le mécanisme d'extension Java. Elles sont regroupées sous forme de fichiers .jar situés dans le répertoire d'extensions .
Classes d'utilisateurs - Classes définies par des développeurs et des tiers qui ne profitent pas du mécanisme d'extension. Vous identifiez l'emplacement de ces classes à l'aide de l'option -classpath sur la ligne de commande ou à l'aide de la variable d'environnement CLASSPATH.
Nous pouvons prouver que X est vraiment le parent de notre Classloader
:
/** run with -Djava.system.class.loader=MyCL to use this classloader */
public class MyCL extends ClassLoader {
public MyCL(ClassLoader parent) { // this constructor must be public, else IllegalAccessException
super(parent);
}
}
Voici notre code principal:
public class Main {
public static void main(String args[]) {
System.out.println("getSystemClassLoader(): " + ClassLoader.getSystemClassLoader());
ClassLoader cl = MyCL.class.getClassLoader();
System.out.println("Classloader of MyCL: " + cl);
Class type_of_cl = cl.getClass();
System.out.println("..and its type: " + type_of_cl);
ClassLoader cl_of_cl = class_of_cl.getClassLoader();
System.out.println("Classloader of (Classloader of MyCL): " + cl_of_cl);
}
}
Il s'agit de la sortie (sur mon système) lorsqu'elle est exécutée à l'aide de la commande Java -Djava.system.class.loader=MyCL Main
(cf. configuration de l'exécution Eclipse ):
getSystemClassLoader (): MyCL @ 1888759
Chargeur de classe de MyCL: Sun.misc.Launcher$AppClassLoader@7fdcde
.. et son type: classe Sun.misc.Launcher $ AppClassLoader
Chargeur de classe de (Chargeur de classe de MyCL): null
Nous pouvons voir que le chargeur de classe de MyCL
est Sun.misc.Launcher$AppClassLoader
, qui est le chargeur de classe système par défaut.
(Par la langue comme vu dans l'autre citation d'Oracle ci-dessus, le chargeur de classe système par défaut est également appelé le chargeur de classe de " Classes d'utilisateurs ". Vissez Oracle pour venir avec 2 noms pour la même chose.)
Une réponse appropriée serait:
Et cela clarifie également la question d'origine.
Quand vous le faites,
Java -Djava.system.class.loader = com.test.MyClassLoader xxx
L'option -D permet de définir les propriétés système dans l'objet Propriétés de l'instance Java.lang.System qui est chargée lors du démarrage de la JVM. L'option modifie uniquement les propriétés en mémoire. Lors d'un prochain appel de la classe XXX ou d'une autre classe, les propriétés par défaut dans le cadre de la classe System seraient à nouveau chargées. Ici, vous avez défini la propriété Java.system.class.loader sur la valeur com.test.MyClassLoader. En d'autres termes, vous souhaitez remplacer le chargeur de classe système par défaut (également appelé le chargeur de classe bootstrap) par votre nouveau chargeur de classe système pour cet appel de votre classe XXX. Le chargeur de classe système par défaut, qui a été chargée dans le cadre du démarrage de la machine virtuelle Java, rechercherait la propriété Java.system.class.loader en mémoire pour trouver le nom de votre chargeur de classe système prioritaire - si défini (dans votre cas, défini sur MyClassLoader) - et chargerait à partir de votre chemin de classe, qui est, par défaut, la racine de votre répertoire de travail (qui doit contenir XXX) ou celle de la variable classpath, en tant que -cp ou en tant que variable d'environnement CLASSPATH, si elle est définie.
Si vous écrivez dans la méthode principale de votre classe XXX
System.out.println(ClassLoader.getSystemClassLoader());
System.out.println(MyClassLoader.class.getClassLoader());
Tu devrais voir
MyClassLoader
(le nouveau chargeur de classe système qui charge XXX)
Sun.misc.Launcher$AppClassLoader
(le chargeur de classe système par défaut qui a chargé votre nouveau chargeur de classe système)