2. Quelles zones sont incluses dans la zone de données d'exécution ?
3. Quelles données sont stockées respectivement dans la pile et le tas ?
4. Pourquoi devrions-nous remplacer la génération permanente (PermGen) par le métaespace (MetaSpace) ?
5. Comprenez-vous la structure de base de l’espace du tas ? Dans quelles circonstances un objet entrera-t-il dans l’ancienne génération ?
6. Dans quelle zone mémoire les gros objets sont-ils placés ?
7. Quel est le processus de création d’objets Java ?
Question Réponse
1. De quelles parties se compose la JVM ?
Réponse : JVM est un exécutablebytecode (.class) ordinateur virtuel de fichier, qui fournit également la gestion de la mémoire, le garbage collection et d’autres mécanismes. Il contient les parties principales suivantes.
Sous-système de chargement de classe : responsable du chargement des fichiers de bytecode (.class) dans la JVM.
Zone de données d'exécution : est la zone mémoire utilisée par la JVM lors de l'exécution.
Moteur d'exécution : responsable de l'interprétation ou de la compilation du bytecode en code machine pour l'exécution du processeur.
Interface de bibliothèque native : fournit un ensemble d'API pour appeler des bibliothèques natives écrites dans le système d'exploitation ou dans d'autres langages.
2. Quelles zones sont incluses dans la zone de données d'exécution ?
Réponse : La zone de données d'exécution est la zone mémoire allouée par la JVM lors de l'exécution d'un programme Java.
Compteur de programme : il s'agit d'un petit espace mémoire et constitue l'adresse de l'instruction de bytecode en cours d'exécution par le thread. Si le thread exécute une méthode native, la valeur de ce compteur n'est pas définie.
Pile de machines virtuelles Java : chaque thread créera une pile de machines virtuelles lors de sa création, qui est utilisée pour stocker la table de variables locales du thread, le cadre d'opérande, le lien dynamique, les informations de sortie de méthode, etc. La pile de machine virtuelle Java contient plusieurs cadres de pile. Le processus allant de chaque méthode appelée jusqu'à la fin de l'exécution correspond au processus consistant à insérer un cadre de pile dans la pile de la machine virtuelle.
Pile de méthodes natives : il s'agit de l'espace préparé par la JVM pour exécuter les méthodes natives. Elle a des fonctions similaires à la pile de machines virtuelles Java. Il s'agit d'un modèle de mémoire qui décrit le processus d'exécution des méthodes natives.
Tas : utilisé pour stocker presque toutes les instances d'objets et tous les tableaux, et constitue la zone principale dans laquelle fonctionne le ramasse-miettes.
Zone méthode : utilisée pour stocker les informations de classe, les constantes, les variables statiques, le code compilé par le compilateur juste à temps, etc. chargés par la JVM. Avant JDK1.8, il était implémenté en tant que génération permanente. À partir du JDK1.8, la génération permanente est remplacée par l'espace d'origine. Metaspace utilise la mémoire locale plutôt que la mémoire tas.
3. Quelles données sont stockées respectivement dans la pile et le tas ?
Réponse : Données stockées dans la pile (pile de machines virtuelles Java) :
Table de variables locales : principalement utilisée pour stocker les paramètres de méthode et les variables locales dans la méthode. Les types de données incluent les types de données de base et les références d'objet.
Pile d'opérandes : utilisée pour stocker temporairement les instructions d'opération et les résultats intermédiaires pendant l'exécution de la méthode.
Lien dynamique : référence au pool de constantes de la classe à laquelle appartient la méthode, utilisée pour résoudre les références de symboles dans la méthode.
Adresse de retour de la méthode : stocke l'adresse de la prochaine instruction exécutée après l'appel de la méthode. Données stockées dans le tas :
Instance d'objet : une instance d'objet créée via le mot-clé new dans le programme, comprenant les propriétés et les méthodes de l'objet.
Tableau : tous les types de tableaux, y compris les tableaux de types de base et les tableaux d'objets.
4. Pourquoi devrions-nous remplacer la génération permanente (PermGen) par le métaespace (MetaSpace) ?
Réponse : Remplacer la génération permanente par du métaespace vise principalement à résoudre certains problèmes et limitations inhérents à la génération permanente et à améliorer les performances et la flexibilité de la JVM.
Améliorer la flexibilité et l'efficacité de la gestion de la mémoire : La taille de la mémoire de la génération permanente est définie au démarrage de la JVM et ne peut pas être ajustée dynamiquement. Metaspace utilise la mémoire locale au lieu de la mémoire tas Java, et sa taille peut être ajustée dynamiquement selon les besoins.
Résolvez le problème du déchargement des classes et de la collecte des déchets : le comportement GC de la génération permanente est complexe et imprévisible, et l'efficacité du recyclage est faible.
Offre de meilleures performances et stabilité : l'utilisation du métaespace rend la gestion de la mémoire JVM plus unifiée et cohérente, car le métaespace, comme les autres zones de mémoire, est géré à l'aide de la mémoire locale. Cela simplifie les stratégies de gestion de la mémoire et améliore les performances et la stabilité globales.
Simplifiez la gestion de la mémoire JVM
5. Comprenez-vous la structure de base de l’espace du tas ? Dans quelles circonstances un objet entrera-t-il dans l’ancienne génération ?
Réponse : La structure de base de l'espace du tas est principalement composée de la nouvelle génération, de l'ancienne génération et de la génération permanente. Après JDK8, la génération permanente est remplacée par le métaespace et utilise la mémoire locale pour le stockage.
Génération Cénozoïque : La progression de la nouvelle génération est subdivisée en la zone Eden et deux zones de survivants (Survivant 0 et Survivant 1)
Zone Eden : les objets nouvellement créés allouent d'abord de la mémoire dans la zone Eden.
Zone survivant (S0, S1) : utilisée pour stocker les objets ayant survécu au garbage collection de nouvelle génération. Après chaque GC mineur, les objets survivants seront copiés entre ces deux zones.
Ancienne génération : objets encore vivants après plusieurs GC mineurs. Le garbage collection (Major GC ou Full GC) est effectué moins fréquemment dans l’ancienne génération.
Génération/métaespace permanent : utilisé pour stocker les métadonnées des classes, y compris les définitions de classe, les constantes, les variables statiques, le code compilé juste à temps, etc.
La situation où l'objet est de l'ancienne génération :
Le seuil d'âge est atteint : chaque objet a un âge lorsque la mémoire est allouée dans la nouvelle génération, et l'âge sera augmenté de 1 après chaque GC Mineur. Lorsque l'âge atteint un certain seuil (15 par défaut), l'objet sera promu à l'ancienne génération.
Objet volumineux : Si l'objet est trop volumineux et dépasse le seuil fixé par la JVM, l'objet allouera directement de l'espace dans l'ancienne génération.
Espace insuffisant dans la zone des survivants : Si la zone des survivants ne dispose pas de suffisamment d'espace pour accueillir tous les objets survivants pendant le GC mineur, ces objets seront
Détermination dynamique de l'âge des objets : Si la taille de tous les objets du même âge dans l'espace Survivant dépasse la moitié de l'espace Survivant, alors les objets dont l'âge est supérieur ou égal à cet âge peuvent entrer directement dans l'ancienne génération.
// 动态年龄计算代码
uint ageTable::compute_tenuring_threshold(size_t survivor_capacity){//survivor_capacity是survivor空间的大小size_t desired_survivor_size =(size_t)((((double) survivor_capacity)*TargetSurvivorRatio)/100);//TargetSurvivorRatio 为50size_t total =0;
uint age =1;while(age < table_size){
total += sizes[age];//sizes数组是每个年龄段对象大小if(total > desired_survivor_size)break;
age++;}
uint result = age < MaxTenuringThreshold ? age : MaxTenuringThreshold;...}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
6. Dans quelle zone mémoire les gros objets sont-ils placés ?
Réponse : Les objets volumineux (très grands tableaux et chaînes) sont généralement alloués directement dans la zone mémoire d'ancienne génération.Il s'agit d'éviter que la nouvelle génération ne se produise fréquemmentCollecte des orduresÀ l'heure actuelle, les objets volumineux sont fréquemment copiés entre la zone Eden et la zone Survivor, améliorant ainsi l'efficacité du ramassage des ordures. Configurez le seuil des gros objets pour entrer directement dans l'ancienne génération :
7. Quel est le processus de création d’objets Java ?
répondre:
Vérification du chargement des classes
Si la classe n'a pas été chargée, connectée et initialisée, la JVM chargera la classe en premier. Cela comprend les étapes suivantes :
Chargement : lisez le fichier de classe via le chargeur de classe et chargez le bytecode de la classe en mémoire.
Connexion : comprend trois étapes : vérification, préparation et analyse. Vérifiez l'exactitude des fichiers de classe, préparez les variables statiques de la classe et allouez de la mémoire, et résolvez les références de symboles en références directes.
Initialisation : Exécute le bloc d'initialisation statique de la classe et l'initialisation des variables statiques.
allocation de mémoire
JVM alloue de la mémoire pour les nouveaux objets dans le tas. La taille de la mémoire allouée est déterminée par la structure de l'objet, y compris l'en-tête de l'objet et les données d'instance.
La JVM dispose de deux manières principales d'allouer de la mémoire :
Bump-the-pointer : si la mémoire du tas est régulière, le pointeur d'allocation n'a besoin que de se déplacer d'une distance spécifiée vers la zone de mémoire libre.
Liste libre : si la mémoire du tas est irrégulière, la JVM doit conserver une liste libre et trouver le bloc approprié dans la liste libre lors de l'allocation de mémoire.
initialiser à la valeur zéro
La JVM initialisera toutes les variables d'instance de l'objet à leurs valeurs par défaut. Par exemple, les variables de type numérique seront initialisées à 0, les variables de type booléen à false et les variables de type référence à null.
Définir l'en-tête de l'objet
Définissez les informations d'en-tête de l'objet dans l'espace mémoire de l'objet, qui incluent le code de hachage de l'objet, l'âge de génération GC, l'indicateur d'état de verrouillage, le verrou détenu par le thread, l'ID de thread biaisé, etc.
Initialisation du constructeur
Appelez le constructeur de l'objet pour terminer l'initialisation de l'objet. Cela inclut l'exécution d'opérations d'initialisation explicites sur les variables d'instance ainsi que sur le code dans le corps du constructeur. Les étapes spécifiques sont les suivantes :
Exécutez le bloc d'initialisation d'instance de la classe.
Exécutez la méthode constructeur de la classe parent de haut en bas selon la hiérarchie d'héritage.
Initialisez les variables d'instance avec des valeurs explicitement spécifiées.
Exécutez la partie principale de la méthode constructeur de la classe.