Machine virtuelle Java - Garbage Collection

Le cycle de vie d'un objet Java est géré par la JVM. Une fois qu'un objet est créé par le programmeur, nous n'avons pas à nous soucier du reste de son cycle de vie. La JVM trouvera automatiquement les objets qui ne sont plus utilisés et récupérera leur mémoire à partir du tas.

Le nettoyage de la mémoire est une opération majeure effectuée par JVM et l'adapter à nos besoins peut améliorer considérablement les performances de notre application. Il existe une variété d'algorithmes de récupération de place fournis par les JVM modernes. Nous devons être conscients des besoins de notre application pour décider de l'algorithme à utiliser.

Vous ne pouvez pas désallouer un objet par programme en Java, comme vous pouvez le faire dans des langages non GC tels que C et C ++. Par conséquent, vous ne pouvez pas avoir de références pendantes en Java. Cependant, vous pouvez avoir des références nulles (références qui font référence à une zone de mémoire où la JVM ne stockera jamais d'objets). Chaque fois qu'une référence nulle est utilisée, la machine virtuelle Java lève une exception NullPointerException.

Notez que s'il est rare de trouver des fuites de mémoire dans les programmes Java grâce au GC, elles se produisent. Nous allons créer une fuite de mémoire à la fin de ce chapitre.

Les GC suivants sont utilisés dans les JVM modernes

  • Collecteur série
  • Collecteur de débit
  • Collecteur CMS
  • Collecteur G1

Chacun des algorithmes ci-dessus effectue la même tâche: trouver des objets qui ne sont plus utilisés et récupérer la mémoire qu'ils occupent dans le tas. Une des approches naïves à cela serait de compter le nombre de références que chaque objet possède et de le libérer dès que le nombre de références devient 0 (cela est également connu sous le nom de comptage de références). Pourquoi est-ce naïf? Considérez une liste chaînée circulaire. Chacun de ses nœuds aura une référence à celui-ci, mais l'objet entier n'est référencé de nulle part, et devrait être libéré, idéalement.

La JVM libère non seulement la mémoire, mais fusionne également les petits mandrins de mémoire en plus gros. Ceci est fait pour éviter la fragmentation de la mémoire.

Sur une note simple, un algorithme GC typique effectue les activités suivantes -

  • Recherche d'objets inutilisés
  • Libérer la mémoire qu'ils occupent dans le tas
  • Coalescence des fragments

Le GC doit arrêter les threads d'application pendant son exécution. En effet, il déplace les objets lors de son exécution et, par conséquent, ces objets ne peuvent pas être utilisés. Ces arrêts sont appelés `` pauses stop-the-world '' et minimiser la fréquence et la durée de ces pauses est ce que nous visons lors du réglage de notre GC.

Coalescence de la mémoire

Une simple démonstration de la fusion de la mémoire est présentée ci-dessous

La partie ombrée correspond aux objets qui doivent être libérés. Même après avoir récupéré tout l'espace, nous ne pouvons allouer qu'un objet de taille maximale = 75 Ko. C'est même après que nous ayons 200 Ko d'espace libre comme indiqué ci-dessous