Ce que JVM a besoin de charger, c'est un flux binaire, qui peut être sous la forme d'un fichier .class ou d'autres formulaires. Si vous le concevez selon les normes de chargement, il n'y aura pas de gros problème.
Ce qui suit analyse principalement les deux questions de mécanisme et de normes:
Tout d'abord, prenons le mécanisme de chargement des fichiers de classe Java, ce qui est similaire au mécanisme de chargement des variables. Il charge d'abord le fichier de classe en mémoire, puis vérifie, analyse et initialise les données, et forme enfin un type Java que la machine virtuelle peut utiliser directement. Étant donné que Java adopte le mécanisme JIT, il sera lent à charger, mais ses avantages sont évidents, il a une forte flexibilité et prend en charge le chargement dynamique et les connexions dynamiques.
Ensuite, parlons du processus de chargement de la classe:
Le processus de base d'un chargement de classe est dans l'ordre suivant, mais certains ne sont pas strictement dans cet ordre, et certains sont dans l'ordre désordonné. Par exemple, le chargement dynamique nécessite l'initialisation puis l'analyse.
1. Chargement
Il appartient à la machine virtuelle de décider, mais il y a aussi des cas où la phase ci-dessus est exécutée car la phase suivante doit être exécutée.
Pour le moment, la machine virtuelle fait trois choses:
Tout d'abord, lisez le flux binaire du fichier via un nom entièrement qualifié;
Deuxièmement, placez les méthodes et variables statiques dans le fichier dans la zone de méthode;
Troisièmement, générez un objet et mettez-le dans le tas en tant que portail d'accès.
Notez que le premier consiste à lire le flux binaire, et il ne dit pas de quel fichier il est lu ou d'où il est lu. Par conséquent, il crée une forte évolutivité dans Java, qui peut provenir de JAR, ZIP ou de la couche réseau, couche de base de données, etc.
Principalement la déclaration d'objet et de méthode.
2. Vérification
Assurez-vous que le flux binaire répond aux exigences de la machine virtuelle et ne répond pas à la vérification.
Premièrement, la vérification du format de fichier, s'il y a des numéros magiques et s'ils répondent aux exigences des fichiers Java;
Deuxièmement, la vérification des métadonnées, qu'il se conforme aux spécifications de code Java, par exemple, que la classe abstraite soit directement instanciée, si la classe ordinaire a un objet de classe parent indirecte ou direct, etc.; Troisièmement, la vérification de Bytecode, analyse le flux de données et le flux de contrôle, et garantit qu'il n'y aura aucun comportement qui nuit à la machine virtuelle, par exemple, s'il faut appeler des instructions inexistantes, s'il faut attribuer la classe parent à la sous-classe, s'il faut affecter l'objet à un objet de ce type, et et etc.;
Quatrièmement, la vérification de référence symbolique, principalement si la description des classes, des variables et de la méthode peut être trouvée, par exemple si le fichier peut être trouvé avec un nom entièrement qualifié, qu'il soit accessible, etc.
Déterminer principalement la structure interne
3. Préparer
L'attribution d'une valeur initiale à une variable de classe est généralement une valeur 0 telle qu'une variable statique, sans attribuer une valeur à une variable d'instance.
4. Analyse
Le processus de conversion des références symboliques dans un pool constant en références directes. La référence symbolique mentionnée ici fait référence au type de variable, et la référence directe fait référence à la poignée qui peut être directement située à l'objet. Classe, méthode, champ, analyse d'interface, obtenir l'objet pertinent en fonction du nom entièrement qualifié et obtenir son type. S'il n'y a pas d'accès à la classe, illégalaccesserror ne sera lancé, aucun champ NosuchFielDerror ne sera lancé, aucune méthode, l'OsuchMethoDerror ne sera lancée, s'il s'agit d'une classe ou non, l'interface sera lancée.
5. Initialisation
Classes de chargement et ressources nécessaires en fonction des exigences du programme. Il n'y a que quatre situations et vous devez initialiser activement avant de pouvoir effectuer la prochaine opération, vous devez donc d'abord effectuer les quatre étapes ci-dessus.
Premièrement, les classes avec des mots clés nouveaux ou statiques, les nouveaux objets génèrent des objets et les charges statiques statiques, ces deux seront évidemment initialisées;
Deuxièmement, si vous utilisez une classe, vous ne pouvez rien y faire;
Troisièmement, les méthodes de la classe de réflexion doivent être initialisées, non?
Quatrièmement, la classe principale d'exécution, la classe qui utilise la méthode principale. D'autres situations d'initialisation passives n'ont pas besoin d'être prises en compte.
Petits exemples:
classe publique Superclass {static {System.out.println ("SuperClass !!");} public static int value = 1;} public class Subclass étend Superclass {static {System.out.println ("Sous-class !!");}} public class TestClassload {public static void main (String [] args)) {System.out.println (Subclass.Value); SuperClass SuperClass = new Subclass ();}} Superclass !! 1SubClass !!Le résultat de l'exécution montre un problème: lorsque la sous-classe appelle la variable de classe parent, la sous-classe n'est pas initialisée car la relation de code pour le moment n'a rien à voir avec la sous-classe; Lorsque la sous-classe est initialisée, la classe parent n'est plus initialisée car la classe parent a été initialisée dans le corps actuel de la méthode. La seule différence entre une interface et une classe parent est que l'initialisation de l'interface ne nécessite pas l'interface parent, et elle ne sera initialisée que lorsque l'interface parent est utilisée, et le même constructeur de classe sera généré.
À l'heure actuelle, le constructeur de classe sera chargé et toutes les variables de la classe seront initialisées. Bien sûr, la classe parent sera initialisée avant la classe infantile.
6. Utiliser
Après le chargement, comment l'appeler, le dessin, le calcul, etc.
7. Désinstallation
La classe ne s'appelle plus
La question de savoir si les deux classes sont égales dépend principalement du premier chargement en utilisant le même chargeur, et la deuxième adresse de nom entièrement qualifiée est la même
Pourquoi poser les questions ci-dessus? Ensuite, nous parlerons d'un mécanisme de chargement d'une machine virtuelle.
Du point de vue des machines virtuelles Java, il y a deux chargeurs de classe, l'un est appelé le chargeur système (bootstrap classloader), et l'autre est appelé le chargeur personnalisé (étend Classloader). Ceci est divisé en deux, l'un est appelé le chargeur d'application et l'autre est appelé le chargeur de classe d'extension, qui est généralement par défaut au premier; et notre chargement d'application est principalement effectué par les trois chargeurs ci-dessus. La relation entre les trois est l'application> Extension> BootsRap. Le mécanisme de délégation des parents fait référence à la combinaison de deux paires. Le chargeur enfant appelle d'abord la méthode du chargeur parent et l'objet cible n'est pas trouvé avant d'utiliser le chargeur pour enfants.
Le pseudo-code est le suivant:
LoadClass (nom de chaîne, booléen résolve) {class c = findloadEdClass () if (c == null) {if (parent! = null) c = parent.loadClass (name, false); c = findbootstrapClassorNull (name);} catch (classnotfoundException e) {} if (c == null) c = findclass (name);}Java préconise que nous écrivions la logique de notre classe d'appels dans FindClass, ce qui nous aidera à utiliser normalement le mécanisme de délégation des parents.
Détruire 1. Réécrivez la classe de chargement
Détruire 2. Utilisez le chargeur de contexte de thread pour permettre au chargeur parent d'appeler la méthode de chargeur pour enfants
Destruction 3. La méthode couramment utilisée pour le chargement à chaud consiste à personnaliser le chargeur de classe et à écraser le module de bogue d'origine - OSGI
Cependant, si les règles entre les chargeurs personnalisées sont confus et qu'il y a un problème de se référer les uns aux autres en même temps, la classe ne sera finalement pas trouvée et les fuites de blocage et de mémoire se produiront.
En ce qui concerne la réparation à chaud, également connue sous le nom de plug-ins, les plus populaires sont Hotfix, Nuwa, DroidFix et Fix, etc. Ces cadres peuvent être trouvés sur GitHub ou ailleurs. Les principes sont comme ci-dessus, les méthodes sont diverses, il y a une couverture, une redirection, etc., grâce à la configuration, à la définition des actions, etc.; En tant que plug-ins, les conditions suivantes doivent être remplies:
1. Peut être installé indépendamment, mais ne peut pas être exécuté indépendamment
2. Soyez en arrière la compatibilité, peut être élargie
3. Il ne peut s'exécuter dans le programme hôte et peut être désactivé ou remplacé
L'exemple d'exemple ci-dessus du mécanisme de chargement de machine virtuel avancé Java est tout le contenu que je partage avec vous. J'espère que vous pourrez vous faire référence et j'espère que vous pourrez soutenir Wulin.com plus.