Cet article vous présentera le mécanisme de chargement de la classe Jvm dans l'apprentissage Java. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il vous sera utile.
La machine virtuelle charge le fichier de classe (flux d'octets binaires) dans la mémoire, vérifie, convertit, analyse et initialise les données, et forme enfin un fichier qui peut être utilisée directement par la machine virtuelle de type Java, cette série de processus est le mécanisme de chargement de la classe.
Une classe commence par son chargement dans la mémoire par la machine virtuelle jusqu'à ce qu'elle soit déchargée de la mémoire. L'ensemble du cycle de vie comprend : chargement— - Vérification - Préparation - Analyse - Initialisation - Utilisation - Désinstallation Ces 7 étapes. Les trois parties de vérification, de préparation et d'analyse sont collectivement appelées connexions.
Le schéma du cycle de vie est le suivant :
L'ordre des cinq étapes de chargement, vérification, préparation, initialisation et déchargement est déterminé, et le Le processus de chargement de la classe doit démarrer dans cet ordre, la phase d'analyse ne l'est pas nécessairement : elle peut démarrer après l'initialisation dans certains cas, c'est aussi pour prendre en charge la liaison dynamique du langage Java.
Lorsque vous rencontrez les quatre instructions new, getstatic, putstatic et Ensurestatic, si la classe n'a pas été initialisée, son initialisation sera déclenché. (Les scénarios les plus courants qui déclenchent ces quatre instructions au travail : nouvelle instanciation d'objets, lecture ou définition de champs statiques de la classe [sauf modifications finales ou champs statiques qui ont été mis dans le pool constant], appel de static méthodes de la classe)
Lors de l'utilisation de la réflexion
Lors de l'initialisation d'une classe, si sa classe parent n'a pas encore été initialisée, vous devez déclencher d'abord l'initialisation de la classe parent
Lorsque la machine virtuelle démarre, vous devez spécifier une classe principale à exécuter (la classe contenant la méthode principale la machine virtuelle le fera en premier). initialiser cette classe
Utiliser lorsque le langage dynamique jdk1.7 est pris en charge, si le résultat final de l'analyse d'une instance java.lang.invoke.MethodHandle est le handle de méthode de REF_getStatic, REF_putStatic, REF_invokeStatic . Si la classe correspondant à ce handle n'a pas été initialisée, vous devez d'abord déclencher son initialisation
Remarque : toutes les méthodes de référencement de la classe ne déclencheront pas l'initialisation (référence passive par exemple). : créer un tableau, référençant les variables modifiées finales et les variables statiques des sous-classes qui font référence aux classes parentes ne déclenchera pas l'initialisation de la sous-classe mais déclenchera l'initialisation de la classe parent
Vérification du format de fichier : Vérifiez si le flux d'octets est conforme à la spécification de format de fichier Class. Par exemple : qu'il commence par le nombre magique 0xCAFEBABE, que les numéros de version majeure et mineure se trouvent dans la plage de traitement de la machine virtuelle actuelle, que les constantes du pool de constantes aient des types non pris en charge...
Vérification des métadonnées : Effectuer une analyse sémantique des informations décrites par le bytecode. Par exemple : cette classe a-t-elle une classe parent et si elle hérite correctement de la classe parent.
Vérification du bytecode : Grâce à l'analyse du flux de données et du flux de contrôle, il est déterminé que la sémantique du programme est légale et logique (pour parler franchement, cela signifie analyser le corps de la méthode du classe pour garantir que la méthode est dans Cela n'endommagera pas la machine virtuelle lors de son exécution).
Vérification de la référence du symbole : Assurez-vous que l'action d'analyse peut être exécutée normalement.
La phase de vérification est très importante, mais pas forcément une phase nécessaire (car elle n'a aucun impact sur la durée d'exécution du programme). Si tout le code en cours d'exécution a été utilisé et vérifié à plusieurs reprises, la vérification peut être désactivée pendant la phase d'implémentation à l'aide du paramètre -Xverify:none.
à allouer formellement de la mémoire aux variables de classe et à définir la valeur initiale de la variable de classe. La mémoire utilisée par ces variables sera allouée dans la zone méthode.
Remarque :
À l'heure actuelle, seules les variables statiques sont allouées, et non les variables d'instance seront allouées avec l'instance d'objet. Dans le tas Java
la valeur initiale est généralement la valeur zéro du type de données. Si vous définissez une variable statique public static int value = 123; alors la valeur initiale de value est 0 au lieu de 123 lors de la phase de préparation.
Les variables modifiées par final sont initialisées à la valeur spécifiée par l'attribut lors de la phase de préparation. Par exemple : public static final int value = 123 ; alors la valeur initiale de value dans la phase de préparation est 123 ;
La phase d'analyse est le processus dans lequel la machine virtuelle remplace les références de symboles dans le pool constant par des références directes . L'action d'analyse est principalement effectuée sur sept types de références de symboles : classes ou interfaces, champs, méthodes de classe, méthodes d'interface, types de méthodes, descripteurs de méthode et qualificatifs de site d'appel.
Référence de symbole : Utilisez un ensemble de symboles pour décrire la cible de la référence. Le symbole peut être n'importe quelle forme de littéral.
Référence directe : un pointeur vers la cible, un décalage relatif ou une poignée qui peut localiser indirectement la cible.
La phase d'initialisation est le processus d'exécution de la méthode du constructeur de classe
Méthode Constructeur de classe
L'ordre dans lequel le compilateur collecte est déterminé par l'ordre dans lequel les instructions apparaissent dans le fichier source ; un bloc de code statique ne peut accéder qu'aux variables définies avant le bloc statique, aux variables définies après celui-ci et aux variables définies dans le bloc statique précédent Les valeurs peuvent être attribuées, mais ne sont pas accessibles. La méthode
非法向前引用示例 public class SuperClass { public static int va; static { value = 1; //可以编译通过 va = value; //报错 非法向前引用 System.out.println("父类初始化"); } public static int value = 123; }
Les blocs statiques ne peuvent pas être utilisés dans les interfaces, mais les opérations d'affectation de variables peuvent toujours être effectuées, donc les interfaces et les classes généreront des méthodes
La machine virtuelle garantit que la méthode
L'équipe de conception de la machine virtuelle a mis l'action "d'obtenir le flux d'octets binaires décrivant cette classe via le nom complet d'une classe" dans le chargement de classe dans Java. en dehors de la machine virtuelle afin que l'application puisse décider comment obtenir les classes requises. Le bloc de code qui implémente cette action est appelé chargeur de classe.
Bootstrap Classloader (Bootstrap Classloader) : Responsable du stockage dans
Extension Classloader : Ce chargeur est implémenté par sun.misc.Launcher$ExtClassLoader, qui est responsable du chargement du répertoire
Application Classloader (Application Classloader) : Ce chargeur est implémenté par sun.misc.Launcher$AppClassLoader, qui est responsable du chargement de la bibliothèque de classes spécifiée sur le chemin de classe utilisateur (ClassPath) . Les développeurs peuvent utiliser ce chargeur directement. S'il n'y a pas de chargeur de classe personnalisé dans l'application, il s'agit du chargeur de classe exécuté par défaut par le programme. (Chargeur système)
我们的应用程序都是由这3种类加载器相互配合进行加载的。如果有必要,还可以加入自定义的类加载器。
这些类加载器之间的关系如下图:
双亲委派模型的工作过程是:如果一个类加载器收到了一个类加载请求,它首先不会自己去尝试加载这个类,而是把这个请求委派给父类加载器去完成,每一层的加载器都是如此,因此所有的加载请求最终都应该到达顶层的启动类加载器。只有当父加载无法完成这个加载请求时,子加载器才会尝试自己去加载。
1、当ApplicationClassLoader加载一个class时,它首先不会自己去尝试加载这个类,而是把类加载请求委派给父类加载器ExtClassLoader去完成。
2、当ExtClassLoader加载一个class时,它首先也不会自己去尝试加载这个类,而是把类加载请求委派给BootStrapClassLoader去完成。
3、如果BootStrapClassLoader加载失败(例如在$JAVA_HOME/jre/lib里未查找到该class),会使用ExtClassLoader来尝试加载;
4、若ExtClassLoader也加载失败,则会使用AppClassLoader来加载,如果AppClassLoader也加载失败,则会报出异常ClassNotFoundException。
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // 先检查此类是否已被加载 Class<?> c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { //委派给父类加载器去加载 if (parent != null) { c = parent.loadClass(name, false); } else { //如果没有父加载器,则调用启动类加载器 c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } //如果父加载器无法加载,则调用本身加载器去加载 if (c == null) { // If still not found, then invoke findClass in order // to find the class. long t1 = System.nanoTime(); c = findClass(name); // this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } }
系统类防止内存中出现多份同样的字节码
保证Java程序安全稳定运行
参考
《深入理解Java虚拟机》
总结:以上就是本篇文的全部内容,希望能对大家的学习有所帮助。更多相关教程请访问Java视频教程,java开发图文教程,bootstrap视频教程!
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!