Les principaux algorithmes de collecte des ordures sont : marquer-effacer, copier et marquer-organiser.
1. Algorithme de marquage-balayage
Marquez les objets à recycler.
Inconvénients de l'algorithme : problèmes d'efficacité, les processus de marquage et d'effacement sont très inefficaces ; problèmes d'espace, un grand nombre de fragments de mémoire seront générés après la collecte, ce qui n'est pas propice à l'allocation d'objets volumineux.
2. Algorithme de copie
L'algorithme de copie divise la mémoire disponible en deux blocs de taille égale A et B. Un seul d'entre eux est utilisé à la fois. la mémoire de A est utilisée. Après cela, copiez les objets survivants vers B et effacez la mémoire de A. Cela améliore non seulement l'efficacité du marquage, car seuls les objets survivants doivent être marqués, mais évite également le problème de fragmentation de la mémoire à le coût de réduction de la mémoire disponible à la moitié de la taille d'origine.
3. Algorithme de marquage-collation
Dans l'ancienne génération, le taux de survie des objets est élevé et l'efficacité de l'algorithme de copie est très faible. Dans l'algorithme mark-compact, tous les objets vivants sont marqués et déplacés vers une extrémité, puis la mémoire en dehors de la limite est directement nettoyée.
Pendant le processus d'analyse d'accessibilité, afin de connaître avec précision les objets associés aux racines GC, l'ensemble du moteur d'exécution doit ressembler à Être gelé à un certain moment dans le temps signifie que tous les threads en cours d'exécution sont suspendus et que la relation de référence de l'objet ne peut pas continuer à changer.
Comment énumérer rapidement les racines GC ?
Les racines GC se trouvent principalement dans les références globales (constantes ou propriétés statiques de classe) et les contextes d'exécution (références dans les tables de variables locales) De nombreuses applications n'ont que des centaines de mégaoctets dans la zone de méthode. être très inefficace.
Dans HotSpot, il est implémenté à l'aide d'un ensemble de structures de données appelé OopMap. Une fois le chargement de la classe terminé, HotSpot calcule quel type de données se trouve à quel décalage dans l'objet et les stocke dans OopMap. Le code local compilé via JIT enregistrera également les emplacements de la pile et des registres qui sont des références. Lorsque la GC se produit, les objets survivants peuvent être rapidement identifiés en analysant les données OopMap.
Comment faire de la GC en toute sécurité ?
Lorsqu'un thread est en cours d'exécution, il ne peut s'arrêter pour GC que lorsqu'il atteint le point de sécurité.
Basé sur la structure de données OopMap, HotSpot peut terminer rapidement la traversée des racines GC. Cependant, HotSpot ne générera pas d'OopMap correspondant pour chaque instruction et enregistrera uniquement ces informations au point de sécurité.
Le choix du point de sécurité est donc très important. S'il est trop petit, le GC peut attendre trop longtemps. S'il est trop fréquent, cela peut entraîner des problèmes de performances d'exécution. Le temps d'exécution de la plupart des instructions est très court et certaines instructions avec un temps d'exécution long sont généralement sélectionnées comme points sûrs, comme les appels de méthode, les sauts de boucle et les sauts d'exception.
Pour plus d'informations sur Safe Point, vous pouvez consulter cet article JVM's Stop The World, Safe Point, Dark Underground World
Comment arrêter tous les threads lorsque GC se produit Exécuter vers le Point sûr le plus proche et faire une pause ?
Lorsque GC se produit, le thread n'est pas directement interrompu, mais un indicateur d'interruption est simplement défini lorsque chaque thread s'exécute vers le point sûr, il interroge activement l'indicateur d'interruption si l'indicateur d'interruption est. c'est vrai, il s'interrompra.
Un problème est ignoré ici. Lorsque GC se produit, les threads en cours d'exécution peuvent s'exécuter jusqu'au point sûr et se bloquer, tandis que les threads en état de veille ou bloqué ne peuvent pas répondre à la demande d'interruption de la JVM pour le moment. accédez au point de sécurité pour suspendre. Dans cette situation, vous pouvez utiliser la région de sécurité pour résoudre le problème.
Safe Region signifie que dans un morceau de code, la relation de référence de l'objet ne changera pas. Il est sûr de démarrer GC n'importe où dans cette région.
1. Lorsqu'un thread rencontre le code de région sûre, il sera d'abord marqué comme étant entré dans la région sûre. Si le GC se produit pendant cette période, la JVM ignorera le thread marqué comme région sûre
2. Lorsque le thread est sur le point de quitter la région sécurisée, il vérifiera si la JVM a terminé le GC. S'il est terminé, il continuera à s'exécuter. Sinon, le thread devra attendre qu'il reçoive un signal. qu'il peut quitter en toute sécurité la Région Sûre
La spécification de la machine virtuelle Java ne stipule pas comment le garbage collector doit être implémenté. Les utilisateurs peuvent combiner les collecteurs utilisés dans chaque zone en fonction des caractéristiques du système.
La photo ci-dessus montre 7 collectionneurs de générations différentes. S'il y a un lien entre deux, cela signifie qu'ils peuvent être utilisés en combinaison.
1. Serial Collector (serial GC)
Serial est un collecteur qui utilise un seul thread et fonctionne dans la nouvelle génération basée sur un algorithme de copie lors de l'exécution de garbage. collection , tous les autres threads de travail doivent être suspendus. Pour un environnement à processeur unique, Serial peut effectuer un garbage collection très efficacement car il n'a pas de surcharge d'interaction avec les threads. Il s'agit du collecteur par défaut pour la nouvelle génération en mode Client.
2. Collecteur ParNew (GC parallèle)
ParNew est en fait une version multithread de la série En plus d'utiliser plusieurs threads pour le garbage collection, le reste de. le comportement est le même que celui de la série.
3. Collecteur Parallel Scavenge (GC de recyclage parallèle)
Parallel Scavenge est un collecteur qui utilise un algorithme de copie multithread et fonctionne dans la nouvelle génération. Il s'agit d'obtenir un débit contrôlable, souvent appelé collecteur « axé sur le débit d'abord ».
Débit = temps d'exécution du code utilisateur / (temps d'exécution du code utilisateur temps de récupération de place)
Parallel Scavenge fournit deux paramètres pour un contrôle précis du débit :
1 , -XX : MaxGCPauseMillis définit le temps de pause maximum pour le garbage collection
2 -XX : GCTimeRatio définit la taille du débit
4. 🎜>Serial Old est un collecteur qui utilise un algorithme de regroupement de marques à thread unique et fonctionne dans l'ancienne génération. Il s'agit du collecteur par défaut de l'ancienne génération en mode Client.
5. Parallel Old Collector (Parallel GC)
Parallel Old est un collecteur qui utilise le multi-threading basé sur un algorithme de regroupement de marques et fonctionne dans l'ancienne génération. Dans les situations où le débit est important et les ressources CPU sensibles, la combinaison de collecteurs Parallel Scavenge et Parallel Old peut être prioritaire.
6. CMS Collector (Concurrent GC)
CMS (Concurrent Mark Sweep) est un collecteur qui vise à obtenir le temps de pause de recyclage le plus court et fonctionne dans l'ancienne génération. est implémenté sur la base de l'algorithme "mark-clear". L'ensemble du processus est divisé en 4 étapes suivantes :
1
Marquage initial
: Ce processus marque uniquement les objets que le GC suivant. Les racines peuvent être directement associées. Mais cela arrêtera toujours le monde ;
2 Marquage simultané
: Le processus de traçage des racines GC peut fonctionner avec les threads utilisateur.
3. Remarque
: Utilisé pour corriger la partie de l'enregistrement qui change en raison du fait que le programme utilisateur continue de s'exécuter pendant le marquage simultané. Ce processus suspendra tous les threads, mais le temps de pause est. beaucoup plus long. Le temps est plus court que le marquage simultané ;
4 Nettoyage simultané
: peut fonctionner avec les threads utilisateur.
Inconvénients du collecteur CMS :
1. Il est sensible aux ressources CPU dans la phase concurrente, même s'il ne provoquera pas de pause des threads utilisateur, il occupera une partie des ressources des threads. et réduire le débit total du système.
2. Les déchets flottants ne peuvent pas être traités.Pendant la phase de nettoyage simultanée, l'exécution des threads utilisateur générera toujours de nouveaux objets poubelles qui ne pourront être collectés que dans le prochain GC.
3. Le CMS est implémenté sur la base de l'algorithme Mark-and-Sweep, ce qui signifie qu'un grand nombre de fragments de mémoire seront générés une fois la collecte terminée, ce qui peut entraîner une grande quantité d'espace restant dans l'ancienne génération, mais elle est incapable de trouver un espace continu suffisamment grand pour allouer l'Objet actuel doit déclencher un Full GC au préalable.
Dans l'implémentation JDK1.5, lorsque l'utilisation de l'espace de l'ancienne génération atteint 68 %, le collecteur CMS sera déclenché. Si l'ancienne génération dans l'application ne croît pas trop vite, vous pouvez augmenter le pourcentage de déclenchement via le. -XX:CMSInitiatingOccupancyFraction paramètre , réduisant ainsi le nombre de recyclage de mémoire et améliorant les performances du système.
Dans l'implémentation JDK1.6, le seuil de déclenchement du collecteur CMS a été augmenté à 92 %. Si la mémoire réservée lors du fonctionnement du CMS ne peut pas répondre aux besoins des threads utilisateur, un échec de type « Concurrent Mode Failure » se produira. La machine virtuelle démarre le collecteur Serial Old pour collecter les déchets de l'ancienne génération. Bien entendu, le temps de pause de l'application sera plus long, ce seuil ne peut donc pas être défini trop haut s'il provoque une « échec du mode simultané. " En cas d'échec, cela réduira les performances. , Quant à la manière de définir ce seuil, l'utilisation de l'espace d'ancienne génération doit être surveillée pendant une longue période.
7. Collecteur G1
G1 (Garbage First) est un collecteur fourni par JDK1.7 qui fonctionne dans la nouvelle génération et l'ancienne génération, basé sur "mark- L'algorithme « Collation » est implémenté pour éviter les problèmes de fragmentation de la mémoire une fois la collecte terminée.
Avantages du G1 :
1. Parallélisme et concurrence : utiliser pleinement plusieurs processeurs pour raccourcir le temps de pause de Stop The World ;
2. la collecte est requise Avec la coopération, vous pouvez gérer l'ensemble du tas Java et utiliser différentes méthodes pour traiter les objets nouvellement créés, les objets qui ont survécu pendant un certain temps et qui ont subi plusieurs GC pour obtenir de meilleurs effets de collecte
;3. Intégration spatiale : contrairement à l'algorithme « mark-clear » de CMS, G1 ne générera pas de fragmentation de l'espace mémoire pendant le fonctionnement, ce qui est propice au fonctionnement à long terme des applications. Lors de l'allocation d'objets volumineux, cela n'entraînera pas l'impossibilité de postuler pour un. objet suffisamment grand. La mémoire continue déclenche un GC complet à l'avance
4. Prédiction de pause : un modèle de temps de pause prévisible peut être établi dans G1, permettant aux utilisateurs de spécifier clairement le temps consacré à la collecte des ordures. un segment de temps de M millisecondes. Le temps d'activation ne doit pas dépasser N millisecondes.
Lors de l'utilisation du collecteur G1, la disposition de la mémoire du tas Java est très différente de celle des autres collecteurs. L'ensemble du tas Java sera divisé en plusieurs régions indépendantes de taille égale. La nouvelle génération et l'ancienne génération ne sont pas. Physiquement isolées, elles constituent toutes un ensemble de régions (pas nécessairement consécutives). G1 suivra l'état de collecte des déchets de chaque région (taille de l'espace de recyclage et temps de recyclage), maintiendra une liste de priorités et donnera la priorité à la région ayant la plus grande valeur en fonction du temps de collecte autorisé pour éviter la collecte des déchets de toute la région sur l'ensemble. Tas Java. , garantissant que le collecteur G1 peut collecter autant de déchets que possible dans un temps limité.
Mais voici le problème : en utilisant le collecteur G1, un objet est alloué dans une région et peut avoir une relation de référence avec n'importe quel objet sur le tas Java. Alors, comment déterminer si un objet est vivant et s'il est vivant. est-il nécessaire d'analyser l'intégralité du tas Java ? En fait, ce problème existait également dans les collecteurs précédents. Si vous devez scanner l'ancienne génération en même temps lors du recyclage des objets de la nouvelle génération, l'efficacité de Minor GC sera considérablement réduite.
Pour cette situation, la machine virtuelle fournit une solution : la relation de référence d'objet entre les régions du collecteur G1 et la relation de référence d'objet entre la nouvelle génération et l'ancienne génération dans d'autres collecteurs sont enregistrées dans la structure de données Remembered Set. , utilisé pour éviter une analyse complète du tas. Chaque région de G1 a un ensemble mémorisé correspondant. Lorsque la machine virtuelle découvre que le programme écrit des données de type référence, elle génère une barrière d'écriture pour interrompre temporairement l'opération d'écriture et vérifier si l'objet référencé par la référence est dans le type de référence. même région. Dans le cas contraire, les informations de référence pertinentes sont enregistrées dans l'ensemble mémorisé de la région à laquelle appartient l'objet référencé via CardTable.
Ces choses sur Java GC (1)
Ces choses sur Java GC (2)
Ce qui précède est le contenu de ces choses sur Java GC (2), plus Veuillez faire attention au site Web PHP chinois (www.php.cn) pour le contenu !