La différence entre Class.forName et ClassLoader.loadClass
Chargement des classes
Afin de comprendre la différence entre Class.forName et ClassLoader.loadClass, nous devons d'abord comprendre les étapes de chargement des classes dans JVM Le chargement des classes peut être divisé en les étapes suivantes
.
Chargement : récupérez le flux binaire de la classe via son nom complet, puis chargez-le dans la JVM
Vérification : assurez-vous que les informations contenues dans le flux d'octets du fichier Class répondent aux exigences de la machine virtuelle et ne mettront pas en danger la sécurité de la machine virtuelle
Préparation : Allouer de l'espace mémoire pour les variables de classe et définir la valeur initiale de la variable de classe
Analyse
Initialisation : initialisez les champs et autres ressources selon le code spécifié par l'utilisateur, en exécutant des blocs statiques.
Classe.forName
Quand on passe :
Class.forName("com.test.MyObj")
Lorsque
est utilisé pour obtenir une classe, cela équivaut en fait à appeler Class.forName(className, true, currentLoader). Le deuxième paramètre de cette méthode indique si la classe doit être initialisée à true, donc lorsque Class.forName obtient. l'objet Class, ce sera La classe est automatiquement initialisée. Et le ClassLoader de la classe chargée par Class.forName est le même que le ClassLoader de la classe où Class.forName est appelé.
ClassLoader.loadClass
est différent de Class.forName. Par défaut, ClassLoader.loadClass n'initialise pas la classe, c'est-à-dire que l'étape 初始化 de chargement de la classe n'est pas exécutée, donc le bloc de code statique de la classe ne sera pas exécuté. et utilisez ClassLoader.loadClass, nous pouvons spécifier différents ClassLoader Par exemple :
public class MyObj {
static {
System.out.println("MyObj class init.");
}
}
public class Test implements Cloneable, Serializable {
public static void main(String[] args) throws Exception {
Class.forName("com.test.MyObj");
// ClassLoader.getSystemClassLoader().loadClass("com.test.MyObj");
}
}
Dans le code ci-dessus, l'appel de Class.forName("com.test.MyObj") déclenchera l'exécution du bloc de code statique de MyObj, mais ClassLoader.getSystemClassLoader().loadClass("com.test.MyObj"); ne le fera pas.
Quels sont les avantages de l’utiliser de cette façon ?
Mon hypothèse personnelle est que cela devrait être lié au chargement paresseux de Spring IoC. Afin d'accélérer l'initialisation, Spring IoC utilise de nombreuses technologies de chargement retardé. L'utilisation de classloader n'a pas besoin d'exécuter le code d'initialisation dans la classe. ce qui peut accélérer le chargement. Le travail d'initialisation de la classe est laissé jusqu'à ce que la classe soit réellement utilisée.
La différence entre Class.forName et ClassLoader.loadClass
Chargement des classes
Afin de comprendre la différence entre
.Class.forName
etClassLoader.loadClass
, nous devons d'abord comprendre les étapes de chargement des classes dans JVMLe chargement des classes peut être divisé en les étapes suivantes
Chargement : récupérez le flux binaire de la classe via son nom complet, puis chargez-le dans la JVM
Vérification : assurez-vous que les informations contenues dans le flux d'octets du fichier Class répondent aux exigences de la machine virtuelle et ne mettront pas en danger la sécurité de la machine virtuelle
Préparation : Allouer de l'espace mémoire pour les variables de classe et définir la valeur initiale de la variable de classe
Analyse
Initialisation : initialisez les champs et autres ressources selon le code spécifié par l'utilisateur, en exécutant des blocs statiques.
Classe.forName
Quand on passe :
Lorsqueest utilisé pour obtenir une classe, cela équivaut en fait à appeler
Class.forName(className, true, currentLoader)
. Le deuxième paramètre de cette méthode indique si la classe doit être initialisée àtrue
, donc lorsque Class.forName obtient. l'objet Class, ce sera La classe est automatiquement initialisée.Et le ClassLoader de la classe chargée par Class.forName est le même que le ClassLoader de la classe où
Class.forName
est appelé.ClassLoader.loadClass
est différent de
.Class.forName
. Par défaut,ClassLoader.loadClass
n'initialise pas la classe, c'est-à-dire que l'étape初始化
de chargement de la classe n'est pas exécutée, donc le bloc de code statique de la classe ne sera pas exécuté.et utilisez
ClassLoader.loadClass
, nous pouvons spécifier différents ClassLoader Par exemple :Un exemple
Dans le code ci-dessus, l'appel de
Class.forName("com.test.MyObj")
déclenchera l'exécution du bloc de code statique de MyObj, maisClassLoader.getSystemClassLoader().loadClass("com.test.MyObj");
ne le fera pas.Quels sont les avantages de l’utiliser de cette façon ?
Mon hypothèse personnelle est que cela devrait être lié au chargement paresseux de Spring IoC. Afin d'accélérer l'initialisation, Spring IoC utilise de nombreuses technologies de chargement retardé. L'utilisation de classloader n'a pas besoin d'exécuter le code d'initialisation dans la classe. ce qui peut accélérer le chargement. Le travail d'initialisation de la classe est laissé jusqu'à ce que la classe soit réellement utilisée.