1. Une commande correspond à un processus.
Lorsque nous démarrons un programme Java, c'est-à-dire lorsque nous démarrons une méthode principale, un processus de machine virtuelle Java sera démarré, quelle que soit la complexité du processus. Les différents processus JVM ne s'affecteront pas. C'est pourquoi on dit que le programme Java n'a qu'une seule entrée : la méthode principale, qui est appelée par la machine virtuelle. Les deux méthodes principales correspondent à deux processus JVM, démarrant deux chargeurs de classes différents et exploitant réellement des classes différentes. Ils ne s’influenceront donc pas mutuellement.
2. Chargement de classe.
Lorsque nous utilisons une classe, si la classe n'a pas été chargée en mémoire, le système initialisera la classe via le chargement, la connexion et l'initialisation.
1. Chargement de classe : fait référence à la lecture du fichier de classe de la classe dans la JVM et à la création d'un objet Class pour celui-ci.
2. Connexion de classe : fait référence à la fusion des données binaires de la classe dans le JRE, qui est divisé en trois étapes :
a) Vérification : Vérifiez l'exactitude des données du fichier de classe chargé.
b). Préparation : allouez de l'espace de stockage aux variables statiques de la classe et effectuez l'initialisation par défaut.
c). Analyse : remplacez les références de symboles dans les données binaires de la classe par des références directes.
3. Initialisation : Initialisez les variables statiques et les blocs d'initialisation statiques de la classe.
(Remarque : pour une propriété statique de type final, si la valeur de la propriété a été obtenue au moment de la compilation, l'appel de la propriété n'entraînera pas l'initialisation de la classe, car cela équivaut à utiliser une constante ;
L'utilisation de la méthode ClassLoader() charge uniquement la classe et ne l'initialise pas. )
3. Chargeur de classe.
Le chargeur de classe est responsable du chargement des fichiers .class en mémoire et de la génération des objets java.lang.Class correspondants. Une fois qu'une classe est chargée dans la JVM, elle ne sera plus chargée.
En Java, une classe est identifiée par son nom de classe complet (c'est-à-dire nom du package + nom de classe).
Dans la JVM, une classe est identifiée par son nom de classe complet et son chargeur de classe.
Lorsque la JVM est en cours d'exécution, trois ClassLoaders seront générés, à savoir : BootstrapClassLoader (chargeur de classe racine), ExtClassLoader (chargeur de classe étendu) et AppClassLoader (chargeur de classe système). La structure UML est la suivante :
Parmi eux, BootstrapClassLoader est responsable du chargement de la bibliothèque de classes de base de JRE. Ce n'est pas une sous-classe de ClassLoader et est écrit en C++, nous ne pouvons donc pas le voir en Java. Lorsqu'il est obtenu via la méthode getParent() de sa sous-classe, null sera. être restitué. BootstrapClassLoader est responsable du chargement des bibliothèques de classes de base Java telles que rt.jar et charsets.jar sous la cible JRE.
Comme le montre la figure, ExtClassLoader et AppClassLoader sont des sous-classes de ClassLoader. Vous ne pouvez pas les voir dans l'API, ils se trouvent dans le fichier rt.jar. Les noms de classe complets sont :
sun.misc.Launcher$ExtClassLoader et sun.misc.Launcher$AppClassLoader.
Parmi eux, ExtClassLoader est responsable du chargement du package JAR dans le répertoire d'extension JRE ext, et AppClassLoader est responsable du chargement du package de classe sous le chemin Classpath.
Le test est le suivant :
Copiez le code comme suit :
paquet com.stopTalking.crazy ;
classe publique TestClassLoader {
public static void main (String[] arguments) {
//Récupère le chargeur de classe du thread actuel
Chargeur ClassLoader = Thread.currentThread().getContextClassLoader();
//Récupère le chargeur de classe de la classe System
ClassLoader chargeur1 = System.class.getClassLoader();
//Obtenir le chargeur de classe loader2 de cette classe TestClassLoader
ClassLoader chargeur2 = TestClassLoader.class.getClassLoader();
//Obtenir la classe parent de Loader2
ClassLoader chargeur3 = chargeur2.getParent();
//Obtenir la classe parent de la classe parent de Loader2
ClassLoader chargeur4 = chargeur3.getParent();
System.out.println(chargeur);
System.out.println(loader1);
System.out.println(loader2);
System.out.println(loader3);
System.out.println(loader4);
}
}
Sortie de la console :
Copiez le code comme suit :
//Le chargeur de classe obtenu par la classe de thread actuelle est AppClassLoader
sun.misc.Launcher$AppClassLoader@6b97fd
//La classe System est chargée par le chargeur racine et n'est pas accessible en Java, elle est donc nulle
nul
//Le chargeur de classe de cette classe est bien sûr aussi AppClassLoader
sun.misc.Launcher$AppClassLoader@6b97fd
sun.misc.Launcher$ExtClassLoader@1c78e57
nul