Cet article vous apporte une explication détaillée (images et texte) sur le modèle de mémoire JVM et la zone de données d'exécution. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.
1. Modèle de mémoire Java
Le but du modèle de mémoire Java est : Masque les différences entre les accès à la mémoire pour différents matériels et systèmes d'exploitation.
Le modèle de mémoire Java stipule que toutes les variables sont stockées dans la mémoire principale. Chaque thread possède sa propre mémoire de travail. La mémoire de travail enregistre une copie des variables dans la mémoire principale.
Les opérations de thread sur les variables ne peuvent être effectuées que dans la mémoire de travail et ne peuvent pas lire ou écrire directement des variables dans la mémoire principale.
L'accès aux variables entre les différents threads doit être effectué via la mémoire principale.
1. La relation entre le modèle de mémoire Java et la zone de données d'exécution Java : la mémoire principale correspond au tas Java et la mémoire de travail correspond à la pile Java.
2. Le mot-clé volatile rend visibles les mises à jour des variables en temps réel dans chaque mémoire de travail. Il est utilisé dans le mode singleton de DCL
2. Zone de données d'exécution Java/zone de mémoire
Parce que la zone de données d'exécution de jvm s'est améliorée, donc Il y aura des différences entre les différentes versions de jdk.
1. La zone mémoire jvm avant jdk1.7 a une génération permanente
1. Le rôle du compteur, car le fichier .java est compilé dans un fichier .class, sert d'indicateur de numéro de ligne pour le bytecode exécuté par le thread actuel. Lorsque l'interpréteur de bytecode fonctionne, il sélectionne la prochaine instruction de bytecode à exécuter en modifiant la valeur de cette calculatrice. Chaque thread possède un compteur de programme indépendant.
2. La pile de méthodes locales est la pile qui exécute les méthodes natives locales qui sont implémentées par les machines virtuelles !
3. La pile de machine virtuelle Java décrit le modèle de mémoire lorsque le thread exécute la méthode Java (méthode). Chaque méthode correspond à un cadre de pile, et la table de variables locales dans le cadre de pile stocke les variables de type de données de base et les variables de référence d'objet dans la méthode.
Comme le montre la figure ci-dessus, la table des variables locales enregistre les 8 variables de type de base et les variables de référence d'objet déclarées dans la méthode. Chaque cadre de pile comporte également une référence au pool de constantes d'exécution, qui fait référence au type String. Voici une question d'entretien classique générée par un objet String !
4. Le tas Java est la plus grande pièce de mémoire de la JVM et est partagée par tous les threads. Presque toutes les instances d'objets sont allouées ici, le tas Java est donc également la zone principale du garbage collection JVM. Le tas Java est divisé en la jeune génération et l'ancienne génération ; la jeune génération peut être divisée en espace Eden, de l'espace du survivant et de l'espace du survivant.
Lorsque nous utilisons le nouveau mot-clé pour allouer un objet, l'objet est généré dans le tas Java.
Analysons la situation lorsque l'objet est généré.
Étant donné qu'Eden est le plus grand, les objets nouvellement générés sont alloués à l'espace Eden. Lorsque l'espace Eden est presque plein, un GC mineur est effectué, puis les objets survivants sont copiés. l’espace Du Survivant. À l’heure actuelle, l’espace Eden continue de fournir une mémoire tas à l’extérieur.
Les objets qui seront générés ultérieurement sont toujours placés dans l'espace Eden. Lorsque l'espace Eden sera à nouveau plein, à ce moment-là, l'espace Eden et l'espace From Survivor effectueront une action. GC mineur en même temps, puis les objets survivants seront placés dans l'espace To Survivor. À l’heure actuelle, l’espace Eden continue de fournir une mémoire tas à l’extérieur.
La situation suivante est cohérente avec 2. Lorsque l'espace Eden est presque plein, l'espace Eden et l'espace To Survivor effectuent un GC Mineur, puis les objets survivants sont placés dans l'espace From Survivor.
La situation suivante est cohérente avec 3. Lorsque l'espace Eden est rapide ou lent, l'espace Eden et l'espace From Survivor effectuent un GC mineur, puis les objets survivants sont placés dans l'espace To Survivor.
signifie que l'un des deux survivants est utilisé pour fournir du stockage d'objets. Lorsque l'espace Eden et un certain espace Survivant sont GCed, l'autre espace Survivant ne peut pas contenir les objets qui ont survécu au GC ou c'est le cas d'environ 15 GC Mineurs consécutifs qui seront mis dans l'ancienne génération ; espace.
Lorsque l'espace ancienne génération est également plein, un Major GC est effectué pour recycler l'espace ancienne génération. (Aussi appelé Full GC, Full GC consomme beaucoup de mémoire et doit être évité)
La jeune génération utilise un algorithme de copie : à chaque fois Minor GC copie les objets survivants de la zone Eden et d'une zone Survivant vers une autre zone Survivant. L'ancienne génération utilise un algorithme de marquage-complément : à chaque fois, Major GC déplace les objets survivants vers une extrémité de l'espace mémoire, puis nettoie directement la mémoire en dehors de la limite d'extrémité.
Les objets volumineux tels que les tableaux et les chaînes très longues entrent directement dans l'espace de l'ancienne génération.
5. La zone de méthode est utilisée pour stocker les informations de classe, les constantes finales, les variables statiques et d'autres données chargées par la JVM. Les données de la zone de méthode sont uniques dans l'ensemble du programme. La zone de méthode contient également un pool de constantes d'exécution, qui stocke principalement les littéraux et les références de symboles générés lors de la compilation (placés après le chargement de la classe). Le littéral de l'objet String sera placé dans le pool de constantes d'exécution.
La collecte des déchets dans le domaine des méthodes implique principalement le recyclage des constantes et le déchargement des types.
2. Dans la zone mémoire jvm de jdk1.8 et versions ultérieures, le métaespace remplace la génération permanente
Les propriétés du métaespace et de la génération permanente sont les mêmes. Ce sont deux implémentations du domaine de méthode JVM et ont la même fonction. Cependant, la plus grande différence entre le métaespace et la génération permanente est que le métaespace ne se trouve pas dans la mémoire JVM de la machine virtuelle, mais utilise la mémoire locale.
Pourquoi utiliser le métaespace au lieu de la génération permanente ?
Les chaînes sont stockées dans la génération permanente et sont sujettes à des problèmes de performances et à des débordements de mémoire.
Il est difficile de déterminer la taille des informations de classe et de méthode, il est donc difficile de spécifier la taille de la génération permanente. Si elle est trop petite, cela conduira facilement à une génération permanente. débordement de génération, et s'il est trop grand, cela entraînera facilement le débordement de l'ancienne génération.
La génération permanente apportera une complexité inutile au GC et l'efficacité du recyclage est faible.
Mémoire directe
NIO ajouté après que JDK1.4 a introduit les E/S basées sur les canaux de canal et les tampons tampons, en utilisant directement les fonctions natives. Allocation hors tas la mémoire améliore considérablement les performances d'E/S et évite la copie des données du BIO d'origine entre le tas Java et le tas naïf.
3. Allocation de mémoire lors de la génération de chaîne
Article de référence : Explication détaillée de la chaîne pool constant en Java.
4. Situation de la mémoire lors de la génération d'objets
Analysons nos modèles de mémoire courants pour générer des objets ou des variables de type de données de base. Cela vous donnera une meilleure compréhension de la JVM.
int i =3;, une méthode correspond à un cadre de pile, et les variables de type de données de base dans la méthode sont allouées directement dans le cadre de pile. S'il s'agit d'un type de données de base statique ou final, il est stocké dans le pool de constantes d'exécution, tout comme String.
Object o1 = new Object();, la référence de l'objet (Object o1) est stockée dans le cadre de pile, mais les données de l'objet (new Object()) sont stockées dans le tas Java et le type d'objet données (Classe et autres informations) Stockées dans la zone méthode.
String s1 = new String("abcd");, en utilisant l'objet déclaré avec new, la référence de l'objet (String s1) est stockée dans le cadre de pile, et les données de l'objet (new String("abcd" )) est stocké dans Java Dans le tas, la valeur de chaîne ("abcd") est stockée dans le pool de constantes d'exécution.
String s2 = "abc", la référence de l'objet (String s2) est stockée dans le cadre de pile et la valeur de la chaîne ("abc") est stockée dans le pool de constantes d'exécution.
La relation entre la pile Java, le tas Java et la zone de méthode est à peu près celle indiquée dans l'analyse ci-dessus.
3. Diverses analyses d'exceptions
1. Erreur de dépassement de mémoire du tas Java OutOfMemoryError
Si le tas Java est alloué là-bas. il y a trop d'objets et l'espace mémoire n'est toujours pas suffisant après GC. Le test suivant est effectué en générant cycliquement des objets pour consommer de l'espace mémoire.
Instructions associées : VM Args: -Xms20m -Xmx40m
, indiquant que la mémoire de tas minimale allouée par la JVM est de 20 Mo et le maximum est de 40 Mo.
public static void main(String[] args) { while (true) { List<object> list = new ArrayList(10); list.add(new Object()); } }</object>
2. Erreur de débordement de pile Java StackoverflowError
Si la profondeur de la pile Java est supérieure à la profondeur autorisée par la JVM, cette erreur sera être jeté. Ce qui suit est un test de pile via des appels récursifs infinis.
instructions associées : VM Args: -Xss128k
, indiquant que la capacité de la pile allouée par la JVM est de 128 Ko.
public class StackOOM { private int length = 1; public void stackLeak() { length++; stackLeak(); } public static void main(String[] args) { StackOOM stackOOM = new StackOOM(); stackOOM.stackLeak(); } }
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!