Maison  >  Article  >  Java  >  Explication graphique et textuelle détaillée du mécanisme de récupération de place des machines virtuelles en Java

Explication graphique et textuelle détaillée du mécanisme de récupération de place des machines virtuelles en Java

黄舟
黄舟original
2017-08-09 09:31:531274parcourir

Dans la machine virtuelle Java, la mémoire des objets et des tableaux est allouée dans le tas, et la mémoire principale récupérée par le garbage collector est dans la mémoire du tas. Si les objets ou tableaux créés dynamiquement ne sont pas recyclés à temps pendant l'exécution d'un programme Java et continuent de s'accumuler, la mémoire tas finira par être pleine, conduisant à un MOO.

JVM fournit un mécanisme de récupération de place, appelé mécanisme GC. Grâce au mécanisme GC, les objets indésirables dans le tas peuvent être recyclés en continu pendant le fonctionnement, garantissant ainsi le fonctionnement normal du programme.

Détermination des objets poubelles

Nous savons tous que les objets dits "garbage" font référence à des objets qui ne sont plus utiles lors de l'exécution de notre programme, c'est-à-dire des objets qui ne sont plus utiles. plus en vie. Alors comment juger si les objets dans le tas sont des « déchets » ou des objets qui ne sont plus vivants ?

Méthode de comptage de références

Chaque objet possède un attribut de comptage de références, qui est utilisé pour enregistrer le nombre de fois où l'objet a été référencé. Lorsque le nombre de références est 0, cela signifie que l'objet n'a pas été référencé, que l'objet ne sera pas utilisé et qu'il peut être déterminé comme un objet poubelle. Cependant, cette méthode a un gros bug, c'est qu'elle ne peut pas résoudre le problème des références mutuelles ou des références circulaires entre objets : lorsque deux objets se réfèrent l'un à l'autre, ils n'ont aucune relation de référence avec d'autres objets, et ils ont le même numéro. de références n'est pas 0, il ne sera donc pas recyclé, mais en fait ces deux objets ne sont plus utiles.

Analyse d'accessibilité (méthode de recherche racine)

Afin d'éviter les problèmes causés par l'utilisation du comptage de références, Java utilise la méthode d'analyse d'accessibilité pour déterminer les objets inutiles.

De cette façon, la relation de référence de tous les objets peut être imaginée comme un arbre. À partir du nœud racine GC Racine de l'arbre, tous les objets référencés sont parcourus. Les nœuds de l'arbre sont des objets accessibles. les objets qui ne sont pas au niveau du nœud sont des objets inaccessibles.

Alors, quel type d'objet peut être utilisé comme nœud racine de GC ?

  • Objets référencés dans la pile de machines virtuelles (table de variables locales dans la pile de frames)

  • Objets référencés par des propriétés statiques dans la zone de méthode

  • Objet référencé par des constantes dans la zone de méthode

  • Objet référencé par JNI dans la pile de méthodes locale

Statut de référence

Le mécanisme de garbage collection, qu'il adopte la méthode de comptage de références ou la méthode d'analyse d'accessibilité, est lié à la référence de l'objet. Il existe quatre statuts de référence en Java :

    <.>
  • Références fortes - La plupart des références que nous utilisons sont en fait des références fortes, et c'est la référence la plus couramment utilisée. Si un objet a une référence forte, cela signifie qu'il est dans un état accessible et le garbage collector ne le recyclera jamais. Même si la mémoire système est très limitée, la machine virtuelle Java préfère générer une erreur

    et provoquer le problème. programme se termine anormalement plutôt que de le recycler. L'objet référencé par une référence forte. Par conséquent, les références fortes sont l’une des principales causes des fuites de mémoire Java. OutOfMemoryError

  • Référence logicielle - Un objet n'a qu'une référence logicielle. S'il y a suffisamment d'espace mémoire, le garbage collector ne le récupérera pas. S'il n'y a pas suffisamment d'espace mémoire, la mémoire de ces objets. sera récupéré. Tant que le garbage collector ne le récupère pas, l'objet peut être utilisé par le programme.

  • Référence faible - un objet n'a qu'une référence faible, ce qui revient à être dispensable. Une référence faible est similaire à une référence souple, mais une référence faible a un niveau de référence inférieur. La différence entre les références faibles et les références souples réside dans le fait que les objets comportant uniquement des références faibles ont un cycle de vie plus court. Au cours du processus d'analyse par le thread du ramasse-miettes de la zone mémoire sous sa juridiction, une fois qu'un objet avec uniquement des références faibles est trouvé, sa mémoire sera récupérée, que l'espace mémoire actuel soit suffisant ou non.

  • Référence factice - Un objet ne contient qu'une référence fantôme, cela revient donc à n'avoir aucune référence et peut être recyclé par le ramasse-miettes à tout moment. Les références virtuelles sont principalement utilisées pour suivre les activités des objets en cours de garbage collection, et nous ne les utilisons généralement pas.

Algorithme de collecte des déchets

Grâce à l'algorithme d'analyse d'accessibilité, il peut être déterminé quels objets doivent être recyclés. Alors, comment le recyclage doit-il être effectué ?

Algorithme d'effacement

Tout d'abord, vous devez marquer la mémoire d'objet qui peut être recyclée, puis effacer la mémoire recyclée.

Algorithme de marquage et de balayage (avant recyclage)

Algorithme de marquage et de balayage (après recyclage)

Mais dans ce cas, au fur et à mesure de l'exécution du programme, la mémoire sera continuellement allouée et libérée, et de nombreuses zones de mémoire libres discontinues seront générées dans le tas, c'est-à-dire des fragments de mémoire. De cette façon, même s'il y a suffisamment de mémoire libre, elle risque de ne pas être en mesure d'allouer une mémoire suffisamment grande et peut provoquer des GC fréquents, affectant l'efficacité, voire le MOO.

Algorithme Mark-Compact

Différent de l'algorithme Mark-Clear, l'algorithme Mark-Compact ne nettoie pas directement la mémoire recyclable après le marquage, mais déplace tous les objets survivants vers une extrémité, puis efface le recyclable Récupérer la mémoire.

Algorithme de marquage-collage (avant recyclage)

Algorithme de marquage-collage (après recyclage)

L'avantage est que cela ne provoquera pas de fragmentation de la mémoire.

Algorithme de copie

L'algorithme de copie doit d'abord diviser la mémoire en deux blocs, allouer d'abord de la mémoire sur l'un des blocs de mémoire, lorsque ce bloc de mémoire est alloué, un garbage collection est effectué, puis tous les objets survivants sont copiés dans un autre morceau de mémoire et le premier morceau de mémoire est effacé.

Algorithme de copie (avant recyclage)

Algorithme de copie (après recyclage)

Ceci Le L'algorithme ne produit pas de fragmentation de la mémoire, mais cela équivaut à utiliser seulement la moitié de l'espace mémoire. Dans le même temps, l'algorithme de réplication est lié au nombre d'objets survivants. Si le nombre d'objets survivants est important, l'efficacité de l'algorithme de réplication sera considérablement réduite.

Algorithme de collection générationnel

Dans la machine virtuelle Java, le cycle de vie des objets peut être long ou court. Le cycle de vie de la plupart des objets est très court et seul un petit nombre d'objets le seront. être en mémoire. Il persiste longtemps, les objets peuvent donc être placés dans différentes zones en fonction de leur cycle de vie. Dans le tas de la machine virtuelle Java qui utilise l'algorithme de collecte générationnelle, il est généralement divisé en trois zones, utilisées respectivement pour stocker ces trois types d'objets :

  • Nouvelle génération - objets nouvellement créés, Dans Lorsque le code est en cours d'exécution, de nouveaux objets seront généralement créés en continu. Beaucoup de ces objets nouvellement créés sont des variables locales et deviendront bientôt des objets inutiles. Ces objets sont placés dans une zone de mémoire appelée la jeune génération. La nouvelle génération se caractérise par de nombreux objets poubelles et peu d’objets survivants.

  • Ancienne génération - certains objets ont été créés très tôt et n'ont pas été recyclés après plusieurs GC, mais ont toujours survécu. Ces objets sont placés dans une zone dite de l'ancienne génération. La caractéristique de l’ancienne génération est qu’il existe de nombreux objets survivants et peu d’objets poubelles.

  • Génération permanente - certains objets qui existent en permanence avec le cycle de vie de la machine virtuelle, comme certains objets statiques, constantes, etc. Ces objets sont placés dans une zone appelée génération permanente. La caractéristique de la génération permanente est que ces objets ne nécessitent généralement pas de garbage collection et survivront pendant l'exécution de la machine virtuelle. (Avant Java 1.7, les objets de génération permanente étaient stockés dans la zone de méthode. Les objets de génération permanente dans la zone de méthode Java 1.7 étaient déplacés vers le tas. Dans Java 1.8, la génération permanente a été supprimée du tas. Cette mémoire est la métaespace. )

L'algorithme de collecte générationnelle effectue également un garbage collection basé sur la nouvelle génération et l'ancienne génération.

Pour la zone nouvelle génération, beaucoup d'objets poubelles seront recyclés à chaque GC, et seuls quelques-uns survivront. Par conséquent, l'algorithme de recyclage de copie est utilisé et les quelques objets survivants restants peuvent être copiés pendant la GC.

Dans la zone nouvelle génération, la copie et le recyclage ne sont pas effectués selon le ratio de 1:1, mais divisés en trois zones : Eden, SurvivorA et SurvivorB selon le ratio de 8:1:1. . Parmi eux, Eden signifie le Jardin d'Eden, décrivant les nombreux nouveaux objets qui y sont créés ; la zone Survivant fait référence aux survivants, c'est-à-dire aux objets qui survivent encore après avoir expérimenté GC.

  1. La zone Eden fournit une mémoire tas au monde extérieur. Lorsque la zone Eden est presque pleine, un GC mineur (New Generation GC) est effectué, les objets survivants sont placés dans la zone SurvivorA, et la zone Eden est dégagée

  2. Après l'Eden ; la zone est effacée, elle continuera à être fournie au monde extérieur. Mémoire du tas

  3. Lorsque la zone Eden est à nouveau remplie, un GC mineur (GC nouvelle génération) est effectué sur le Zone Eden et zone SurvivorA en même temps, et les objets survivants sont placés dans la zone SurvivorB et la zone SurvivorA en même temps

  4. La zone Eden continue de fonctionner. fournit une mémoire de tas au monde extérieur et répète le processus ci-dessus, c'est-à-dire qu'une fois la zone Eden remplie, la zone Eden et une certaine zone Survivant. Les objets survivants sont placés dans une autre zone Survivant

  5. Lorsqu'une zone Survivant est remplie et qu'il reste des objets qui n'ont pas été copiés, ou que certains objets Survivent à plusieurs reprises 15 fois. Lorsque la zone ancienne génération est pleine, les objets restants sont placés dans la zone ancienne génération lorsque la zone Survivant est remplie. la zone d'ancienne génération est également remplie, un GC majeur (GC d'ancienne génération) est effectué pour effectuer le garbage collection sur la zone d'ancienne génération.

Les objets de la zone d'ancienne génération ont généralement une longue période de survie. Au cours de chaque GC, il y a plus d'objets survivants, donc l'algorithme de marquage est utilisé. sont déplacés pendant le GC, ce qui ne provoquera pas de fragmentation de la mémoire.

Types de déclencheurs GC

La machine virtuelle Java imprimera des informations sur chaque déclencheur GC et vous pourrez analyser les raisons du déclenchement du GC en fonction des journaux.

  • GC_FOR_MALLOC : Indique que le GC est déclenché par une mémoire insuffisante lors de l'allocation d'objets sur le tas.

  • GC_CONCURRENT : Lorsque la mémoire tas de notre application atteint une certaine quantité, ou peut être considérée comme étant presque pleine, le système déclenchera automatiquement une opération GC pour libérer la mémoire.

  • GC_EXPLICIT : Indique que le GC est déclenché lorsque l'application appelle l'interface System.gc, VMRuntime.gc ou reçoit le signal SIGUSR1.

  • GC_BEFORE_OOM : indique que le GC est déclenché par le dernier effort avant de se préparer à lever une exception MOO.

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn