[Introduction] Nous sommes en 2017, mais deux choses restent un mystère pour la plupart des développeurs : le ramassage des ordures et le sexe opposé (on se moque encore des codeurs). Comme je ne connais pas grand-chose à ce dernier, j’ai pensé essayer de parler du premier.
Nous sommes en 2017, mais deux choses restent un mystère pour la plupart des développeurs : le ramassage des ordures et le sexe opposé (on se moque encore des codeurs). Comme je ne connais pas grand-chose à ce dernier, je pense que je vais essayer de parler du premier. Surtout avec l'arrivée de Java 8, de nombreux changements et améliorations majeurs ont eu lieu dans ce domaine, dont le plus important est le. Suppression de la génération persistante (PermGen) et quelques nouvelles optimisations intéressantes (qui seront mentionnées plus tard).
En parlant de collecte des déchets, de nombreuses personnes comprennent son concept et l'appliquent dans la programmation quotidienne. Pourtant, il y a beaucoup de choses que nous ne comprenons pas très bien, et c’est de là que vient la douleur. La plus grande idée fausse à propos de la JVM est qu'elle n'a qu'un seul ramasse-miettes, alors qu'en réalité elle en a quatre différents, chacun avec ses propres forces et faiblesses. La JVM ne choisit pas automatiquement l'un par rapport à l'autre, c'est à vous et moi de décider, car différents collecteurs peuvent entraîner des différences significatives en termes de débit et de temps de pause des applications.
Ce que ces quatre algorithmes de collecte ont en commun, c'est qu'ils sont tous générationnels, ce qui signifie qu'ils divisent le tas géré en plusieurs régions. Cela suppose qu'il y a beaucoup de objets dans le tas Le. Le cycle de vie est très court et peut être recyclé rapidement. Il y a eu de nombreuses introductions sur ce sujet, j'ai donc ici l'intention de parler directement de ces différents algorithmes, ainsi que de leurs forces et faiblesses.
Le collecteur série est le plus simple. Vous n'envisagerez même pas de l'utiliser car il est principalement destiné aux environnements monothread (tels que 32 bits ou Windows) et. un tas plus petit. Ce collecteur gèle tous les threads d'application lorsqu'il fonctionne, ce qui rend totalement impossible son utilisation par les applications côté serveur.
Comment l'utiliser : vous pouvez activer le paramètre JVM -XX:+UseSerialGC pour l'utiliser.
Le suivant est le collecteur parallèle (Parallel collecteur). Il s'agit du collecteur par défaut de la JVM. Comme son nom l'indique, son plus grand avantage est qu'il utilise plusieurs threads pour analyser et compacter le tas. Son inconvénient est qu'il mettra en pause le thread d'application, qu'il s'agisse d'un GC mineur ou d'un GC complet. Le collecteur parallèle est particulièrement adapté aux applications qui peuvent tolérer des pauses et tenter de réduire la surcharge du processeur provoquée par le collecteur.
Après le collecteur parallèle se trouve le collecteur CMS (concurrent-mark-sweep). Cet algorithme utilise plusieurs threads (simultanés) pour analyser le tas et marquer les objets qui ne sont plus utilisés et peuvent être recyclés (balayage). Cet algorithme entrera dans un mode "stop the world" dans deux situations : Lors du marquage initial de l'objet racine (point d'entrée du thread dans l'ancienne génération ou statiquevariable peut les objets qui ont été marqués) et lorsque cet algorithme s'exécute simultanément, l'application change l'état du tas afin qu'elle doive revenir en arrière et confirmer à nouveau que les objets qu'elle a marqués sont corrects.
Le plus gros problème avec l'utilisation de ce collecteur est que vous rencontrerez un échec de promotion, qui fait référence à la situation où des conditions de concurrence se produisent lors du recyclage de la nouvelle génération et de l'ancienne génération. Si le collectionneur a besoin de promouvoir de jeunes objets auprès de l'ancienne génération et qu'il n'y a pas d'espace supplémentaire dans l'ancienne génération à ce moment-là, il ne peut d'abord effectuer qu'un GC complet STW (Stop The World) - c'est la bonne situation. ce que CMS veut éviter. Pour garantir que cela ne se produise pas, vous devez soit augmenter la taille de l'ancienne génération (ou augmenter la taille du tas entier), soit allouer des threads d'arrière-plan au collecteur afin qu'il puisse rivaliser avec la vitesse d'allocation des objets. .
Un autre inconvénient de cet algorithme est qu'il utilise plus de ressources CPU que le collecteur parallèle. Il utilise plusieurs threads pour effectuer l'analyse et le recyclage, afin que l'application puisse continuer à fournir des niveaux de débit plus élevés. Pour la plupart des programmes de longue durée, la suspension des applications leur est très préjudiciable. À l'heure actuelle, vous pouvez envisager d'utiliser le recycleur CMS. Cependant, cet algorithme n'est pas activé par défaut. Vous devez spécifier XX:+UseConcMarkSweepGC pour l'activer. En supposant que votre tas est inférieur à 4G et que vous souhaitez allouer plus de ressources CPU pour éviter la suspension des applications, c'est alors le collecteur que vous devez choisir. Cependant, si le tas est supérieur à 4G, vous préférerez peut-être utiliser le dernier – le collecteur G1.
Le collecteur G1 (Garbage first) a été introduit pour la première fois dans la mise à jour 4 du JDK 7. Son objectif de conception est de mieux prendre en charge les tas de plus de 4 Go. Le collecteur G1 divise le tas en régions dont la taille varie de 1 Mo à 32 Mo et utilise plusieurs threads d'arrière-plan pour les analyser. Le collecteur G1 analysera en premier les zones contenant le plus de déchets, d'où son nom (Garbage first). Ce collecteur peut être activé avec l'indicateur -XX:UseG1GC.
Cette stratégie réduit la possibilité que le tas soit épuisé avant que le thread d'arrière-plan n'ait fini d'analyser les objets inutiles. Dans ce cas, le collecteur doit mettre l'application en pause, ce qui entraînera le recyclage STW. Un autre avantage de G1 est qu'il compacte toujours le tas, alors que le collecteur CMS ne le fait que lors d'un GC complet.
Au cours des dernières années, Dadu a été un domaine controversé. De nombreux développeurs sont passés du modèle mono-machine aux microservices et composants multi-machines . 🎜>Architecture. Cela est dû à un certain nombre de facteurs, notamment l'isolement des composants d'application, la simplification du déploiement et l'évitement de la surcharge liée au rechargement des classes d'application en mémoire (cela a été amélioré dans Java 8). Cependant, le principal espoir de cela est d'éviter les longues pauses « arrêter le monde » dans les grands GC (qui prennent plusieurs secondes pour se terminer lors d'une grande collection). Les technologies de conteneurs comme
Dockeraccélèrent également ce processus et vous permettent de déployer facilement plusieurs applications sur la même machine physique. Collecteur Java 8 et G1
( String déduplication). Étant donné que les chaînes (y compris leur char[]array interne) occupent la majeure partie de l'espace du tas, cette nouvelle optimisation est conçue pour permettre au collecteur G1 d'identifier ces chaînes répétées dans le tas et de les pointer vers le même caractère interne. [] pour éviter plusieurs copies de la même chaîne, ce qui rendrait l'utilisation du tas inefficace. Vous pouvez utiliser le paramètre JVM -XX:+UseStringDeduplication pour essayer cette fonctionnalité. Java 8 et génération persistante
Chaque collecteur dispose de nombreux commutateurs et options de réglage différents, qui peuvent augmenter ou diminuer le débit, en fonction du
comportementspécifique de votre application.
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!