En ce qui concerne la collection Garbage (GC), de nombreuses personnes l'associeront naturellement à Java. En Java, les programmeurs n'ont pas besoin de se soucier de l'attribution dynamique de la mémoire et de la collecte des ordures, tout cela est laissé au JVM pour gérer.
Comme son nom l'indique, la collecte des ordures est de libérer l'espace occupé par les ordures. Donc, en Java, quel type d'objets sera considéré comme des «ordures»? Ainsi, lorsque certains objets sont déterminés à être des ordures, quelle stratégie doit être utilisée pour recycler (libre espace)? Quelles sont les collectionneurs typiques des machines virtuelles commerciales actuelles? Discutons de ces questions un par un. Voici le plan du répertoire de cet article:
Comment déterminer si un objet est «ordures»?
Algorithme de collecte de déchets typique
1. Comment déterminer si un objet est "ordures"?
Dans cette section, nous comprenons d'abord la question la plus fondamentale: si nous déterminons qu'un objet est «ordures»? Étant donné que la tâche du collecteur des ordures est de recycler l'espace occupé par l'objet à ordures pour une utilisation par de nouveaux objets, comment le collecteur des ordures détermine-t-il qu'un objet est "à ordures"? Autrement dit, comment juger qu'un objet peut être recyclé.
En Java, il est associé à des objets via des références, c'est-à-dire que si vous souhaitez faire fonctionner des objets, cela doit être fait par le biais de références. Ensuite, il est évident qu'un moyen facile est de juger si un objet peut être recyclé par le comptage de références. Sans perdre la généralité, si un objet n'a aucune référence qui lui est associé, cela signifie que l'objet est tout à fait peu susceptible d'être utilisé ailleurs, puis l'objet devient un objet recyclable. Cette méthode devient la méthode de comptage de référence.
Cette méthode est caractérisée par sa simple implémentation et sa grande efficacité, mais elle ne peut pas résoudre le problème des références circulaires, donc cette méthode n'est pas adoptée en Java (Python utilise la méthode de comptage de référence). Regardez le code suivant:
classe publique Main {public static void main (String [] args) {myObject object1 = new myObject (); MyObject object2 = new myObject (); object1.object = object2; Object2.Object = Object1; object1 = null; object2 = null; }} classe myObject {public objet objet = null;}Les deux dernières phrases attribuent à Object1 et Object2 à NULL, ce qui signifie que les objets pointés par Object1 et Object2 ne sont plus accessibles, mais parce qu'ils se réfèrent les uns aux autres, leur nombre de références n'est pas 0, alors le collecteur de déchets ne les recyclera jamais.
Pour résoudre ce problème, la méthode d'analyse de l'accessibilité est adoptée en Java. L'idée de base de cette méthode est de rechercher une série d'objets "GC Roots" comme point de départ. S'il n'y a pas de chemin accessible entre les "racines GC" et un objet, l'objet est dit inaccessible. Cependant, il convient de noter que l'objet jugé inaccessible ne peut pas nécessairement devenir un objet recyclable. Un objet jugé comme inaccessible doit passer par au moins deux processus de marquage pour devenir un objet recyclable. S'il n'y a toujours pas de possibilité de devenir un objet recyclable pendant ces deux processus de marquage, il deviendra essentiellement un objet recyclable.
Quant à la façon dont la méthode d'analyse de l'accessibilité est opérée, je ne l'ai pas encore comprise très clairement. Si un ami est plus clair, donnez-moi quelques conseils.
Voyons un exemple ci-dessous:
Objet aOBj = new object (); objet bobj = new object (); objet cobj = new object (); aOBj = bobj; aOBj = cobj; cobj = null; aOBj = null;
Quelle ligne peut rendre un objet recyclable? Le code sur la ligne 7 fera que les objets deviennent des objets recyclables. Quant à savoir pourquoi il est laissé aux lecteurs de penser par eux-mêmes.
Jetons un coup d'œil à un autre exemple:
String str = new String ("Hello"); sofTreference <string> sr = new softreference <string> (new String ("java")); faibleSeference <string> wr = new FaibleReference <string> (new String ("world"));Laquelle de ces trois phrases rendra un objet de chaîne recyclable? Les phrases 2 et 3, et la phrase 2 déterminera l'objet String comme un objet recyclable en cas de mémoire insuffisante, et dans la troisième phrase, l'objet String sera déterminé comme un objet recyclable dans tous les cas.
Enfin, résumons les situations communes dans lesquelles les objets sont jugés comme des objets recyclables qui sont généralement rencontrés:
1) Affichez la valeur d'une référence à NULL ou pointez la référence qui a déjà indiqué un objet à un nouvel objet, comme le code suivant:
Objet obj = nouveau objet (); obj = null; objet obj1 = nouvel objet (); objet obj2 = nouveau objet (); obj1 = obj2;
2) Référence locale à l'objet indiqué, comme le code suivant:
void fun () {...... pour (int i = 0; i <10; i ++) {objet obj = new object (); System.out.println (obj.getClass ()); }}Chaque fois que la boucle est exécutée, l'objet généré deviendra un objet recyclable.
3) Seules les références faibles sont associées à des objets, tels que:
FaibleReference <string> wr = new LowerReference <string> (new String ("World"));2. Algorithme de collecte des ordures typique
Après avoir déterminé quelles ordures peuvent être recyclées, le collecteur des ordures doit faire est de commencer la collecte des ordures, mais un problème impliqué est: comment collecter efficacement les ordures. Étant donné que la spécification de la machine virtuelle Java ne rend pas compte des réglementations claires sur la façon de mettre en œuvre un collecteur de déchets, les machines virtuelles de chaque fabricant peuvent implémenter un collecteur de déchets de différentes manières, donc seules les idées de base de plusieurs algorithmes de collecte de déchets courants sont discutés ici.
1.Lek-sweep (Mark-Clear) Algorithme
Il s'agit de l'algorithme de collecte des ordures le plus basique. La raison pour laquelle il est dit la plus fondamentale est qu'il est le plus facile à mettre en œuvre et l'idée la plus simple. L'algorithme de compensation de marque est divisé en deux étapes: l'étape de marquage et l'étape de compensation. La tâche de l'étape de marquage est de marquer tous les objets qui doivent être recyclés, et l'étape de compensation consiste à recycler l'espace occupé par les objets marqués. Le processus spécifique est illustré dans la figure ci-dessous:
Il peut être facilement vu à partir de la figure que l'algorithme de compensation de marque est plus facile à mettre en œuvre, mais il y a un problème sérieux qu'il est facile de générer des fragments de mémoire. Trop de fragments peuvent entraîner l'incapacité de trouver suffisamment d'espace lors de l'allocation d'espace pour les grands objets dans le processus ultérieur et de déclencher une nouvelle action de collecte des ordures à l'avance.
2. Copie (copie) Algorithme
Afin de résoudre les lacunes de l'algorithme Mark-Sweep, l'algorithme de copie a été proposé. Il divise la mémoire disponible en deux morceaux de taille égale par capacité, en utilisant un seul morceau à la fois. Lorsque ce morceau de mémoire est utilisé, copiez l'objet encore vivant à une autre pièce, puis nettoyez l'espace mémoire utilisé à la fois, afin que les problèmes de fragmentation de la mémoire ne se produisent pas. Le processus spécifique est illustré dans la figure ci-dessous:
Bien que cet algorithme soit simple à implémenter, efficace à exécuter et pas facile à générer une fragmentation de la mémoire, il est coûteux d'utiliser l'espace mémoire car la mémoire qui peut être utilisée est réduite à la moitié de celle d'origine.
De toute évidence, l'efficacité de l'algorithme de copie a beaucoup à voir avec le nombre d'objets survivants. S'il y a beaucoup d'objets survivants, l'efficacité de l'algorithme de copie sera considérablement réduite.
3. Algorithme de compact de marque (Mark-Collation)
Afin de résoudre les lacunes de l'algorithme de copie et d'utiliser pleinement l'espace mémoire, l'algorithme de compact Mark est proposé. L'algorithme marque la même chose que Mark-Sweep, mais après avoir terminé la marque, il ne nettoie pas directement les objets recyclables, mais déplace tous les objets vivants à une extrémité, puis nettoie la mémoire à l'extérieur de la limite d'extrémité. Le processus spécifique est illustré dans la figure ci-dessous:
4. Algorithme de collecte générationnelle
L'algorithme de collecte de génération est actuellement utilisé par la plupart des collectionneurs JVM Garbage. Son idée principale est de diviser la mémoire en plusieurs régions différentes selon le cycle de vie de la survie de l'objet. D'une manière générale, la zone de tas est divisée en l'ancienne génération et la jeune génération. La caractéristique de l'ancienne génération est que seul un petit nombre d'objets doivent être recyclés chaque fois que les ordures sont collectées, tandis que la caractéristique de la nouvelle génération est qu'un grand nombre d'objets doivent être recyclés chaque fois que les ordures sont collectées. L'algorithme de collecte le plus approprié peut alors être adopté en fonction des caractéristiques des différentes générations.
À l'heure actuelle, la plupart des collectionneurs d'ordures adoptent l'algorithme de copie pour la nouvelle génération, car dans la nouvelle génération, la plupart des objets doivent être recyclés chaque fois que la collection de ordures est collectée, ce qui signifie que le nombre d'opérations qui doivent être copiés est relativement petit, mais en réalité, l'espace de la nouvelle génération n'est pas divisé selon un rapport 1: 1. D'une manière générale, la nouvelle génération est divisée en un plus grand espace Eden et deux plus petits espaces de survivants. Chaque fois que l'espace Eden et l'un des espaces de survivants sont utilisés, lorsqu'ils sont recyclés, les objets encore survivants dans Eden et survivant sont copiés dans un autre espace de survivant, puis les espaces Eden et les survivants qui viennent d'être utilisés sont nettoyés.
Parce que la vieillesse est que seul un petit nombre d'objets sont recyclés à chaque fois, l'algorithme de compact Mark est généralement utilisé.
Notez qu'il existe une autre génération en dehors de la zone du tas, qui est la génération permanente, qui est utilisée pour stocker des classes, des constantes, des descriptions de méthodes, etc. Le recyclage de la génération permanente recycle principalement deux parties: les constantes jetées et les classes inutiles.
3. collection de déchets typique
L'algorithme de collecte des ordures est la base théorique du recyclage de la mémoire, et le collecteur des ordures est l'implémentation spécifique du recyclage de la mémoire. Ce qui suit est une description de plusieurs collectionneurs d'ordures fournis par la machine virtuelle Hotspot (JDK 7). Les utilisateurs peuvent combiner les collectionneurs utilisés dans chaque époque en fonction de leurs propres besoins.
1. Sérial / en série Old
L'ancien collecteur en série / série est le collectionneur le plus fondamental et le plus ancien. Il s'agit d'un seul collecteur de threads et doit suspendre tous les threads utilisateur lorsqu'il fait la collecte des ordures. Le collecteur en série est un collectionneur pour la nouvelle génération, en utilisant l'algorithme de copie, et l'ancien collecteur en série est un collectionneur pour l'ancienne génération, en utilisant l'algorithme de compact Mark. Son avantage est qu'il est simple et efficace, mais son désavantage est qu'il provoquera des pauses aux utilisateurs.
2.Parnew
Le Parnew Collector est une version multi-thread du collecteur en série qui utilise plusieurs threads pour la collection de déchets.
3. Éclavenge parallèle
Parallel Scavenge Collector est une nouvelle génération de collectionneurs multithreads (collectionneurs parallèles). Il n'a pas besoin de suspendre d'autres threads utilisateur lors du recyclage. Il utilise l'algorithme de copie. Ce collectionneur est différent des deux premiers collectionneurs. Il s'agit principalement d'obtenir un débit contrôlé.
4. Vieux parallèle
Parallel Old est une ancienne version de Parallel Scavenge Collector (Parallel Collector) utilisant des algorithmes multithreading et mark-compact.
5.CMS
Le collecteur CMS (Current Mark Sweep) est un collecteur visant à obtenir le temps de pause de récupération le plus court. Il s'agit d'un collectionneur simultané qui utilise l'algorithme Mark-Sweep.
6.G1
Le collectionneur G1 est la réalisation la plus pointe du développement de la technologie des collectionneurs d'aujourd'hui. Il s'agit d'un collecteur pour les applications côté serveur qui peuvent utiliser pleinement les environnements multi-CPU et multi-core. Il s'agit donc d'un collecteur parallèle et de concurrence, et il peut construire un modèle de temps de pause prévisible.
Voici quelques choses sur l'allocation de la mémoire:
Dans une direction générale, l'allocation de mémoire des objets est allouée sur le tas. Les objets sont principalement alloués dans la nouvelle génération de l'espace Eden et de l'espace, et dans de rares cas, ils seront directement alloués dans la vieillesse. Si l'espace de la nouvelle génération d'espace Eden et de l'espace est insuffisant, un GC sera initié. Si le GC est effectué, l'espace Eden et de l'espace peuvent accueillir l'objet et sont placés dans l'espace Eden et dans l'espace.
Pendant le processus GC, les objets survivants dans l'espace Eden et dans l'espace seront déplacés vers l'espace, puis l'espace Eden et de l'espace seront nettoyés. Si l'espace ne peut pas être suffisant pour stocker un objet pendant le nettoyage, il déplacera l'objet vers la vieillesse. Après GC, l'espace Eden et l'espace sont utilisés. La prochaine fois que vous GC, l'objet survivant sera copié à partir de l'espace et la boucle sera répétée. Lorsqu'un objet échappe à GC une fois dans la zone des survivants, l'âge de son objet sera augmenté de 1. Par défaut, si l'objet atteint 15 ans, il passera à l'âge moyen de la vieillesse.
D'une manière générale, les grands objets seront directement alloués à la vieillesse. Les soi-disant grands objets se réfèrent à des objets qui nécessitent une grande quantité d'espace de stockage continu. Le type le plus courant d'objets importants est de grands tableaux, tels que:
octet [] data = nouvel octet [4 * 1024 * 1024]
Ce type d'espace de stockage sera généralement alloué directement chez les personnes âgées.
Bien sûr, les règles d'allocation ne sont pas fixes à 100%, ce qui dépend du type de combinaison de collection de déchets et des paramètres pertinents du JVM actuellement utilisés.
Ce qui précède est tout le contenu de cet article. J'espère que cela sera utile à l'apprentissage de tous et j'espère que tout le monde soutiendra davantage Wulin.com.