Question

J'espère une question simple. Prenons par exemple une liste à liens circulaires:

class ListContainer
{
  private listContainer next;
  <..>

  public void setNext(listContainer next)
  {
    this.next = next;
  }
}

class List
{
  private listContainer entry;
  <..>
}

Comme il s’agit d’une liste à liens circulaires, lorsqu’un seul élément est ajouté, il est référencé à lui-même dans la variable suivante. Lors de la suppression du seul élément de la liste, l'entrée est définie sur null. Est-il nécessaire de définir ListContainer.next sur null également pour permettre à Garbage Collector de libérer sa mémoire ou gère-t-il automatiquement ces références à soi-même?

Était-ce utile?

La solution

Les éboueurs qui comptent uniquement sur le comptage de références sont généralement vulnérables au non-recueil de structures auto-référentielles telles que celle-ci. Ces GC reposent sur le décompte du nombre de références à l’objet afin de déterminer si un objet donné est accessible.

Les méthodes de comptage sans référence appliquent un test d'accessibilité plus complet pour déterminer si un objet peut être collecté. Ces systèmes définissent un objet (ou un ensemble d'objets) qui est toujours supposé accessible. Tout objet pour lequel des références sont disponibles à partir de ce graphe d'objets est considéré comme non admissible à la collecte. Tout objet non directement accessible à partir de cet objet ne l'est pas. Ainsi, les cycles ne finissent pas par affecter l’accessibilité et peuvent être collectés.

Voir également la page Wikipedia sur suivi des éboueurs .

Autres conseils

Les références circulaires constituent un problème (résoluble) si vous comptez les compter afin de déterminer si un objet est mort. Aucune implémentation Java n'utilise le comptage de références, autant que je sache Les nouveaux JRE Sun utilisent un mélange de plusieurs types de CPG, tous, je pense, à balayer ou à copier.

Pour en savoir plus sur la collecte des ordures en général, consultez la Wikipedia , et d'autres articles sur java GC ici et ici , par exemple.

La réponse à cette question dépend de la mise en œuvre. La machine virtuelle Java Sun garde la trace de certains ensembles d’objets racine (threads, etc.) et, lorsqu’elle a besoin de procéder à un nettoyage de la mémoire, trace quels objets sont accessibles à partir de ceux-ci et les enregistre, en ignorant le reste. Il est en fait plus compliqué que cela de permettre certaines optimisations, mais c'est le principe de base. Cette version ne s’intéresse pas aux références circulaires: tant qu’aucun objet vivant ne contient une référence à un objet mort, il peut être GCed.

Les autres machines virtuelles peuvent utiliser une méthode appelée comptage de références. Lorsqu'une référence à l'objet est créée, un compteur est incrémenté, et lorsque la référence sort de la portée, le compteur est décrémenté. Si le compteur atteint zéro, l'objet est finalisé et les ordures collectées. Cette version, cependant, permet la possibilité de références circulaires qui ne seraient jamais ramassées. Par souci de sécurité, nombre de ces machines virtuelles virtuelles incluent une méthode de sauvegarde permettant de déterminer les objets réellement morts et exécutées périodiquement pour résoudre les auto-références et défragmenter le segment de mémoire.

En dehors de la non-réponse (les réponses existantes sont plus que suffisantes), vous pouvez consulter un livre blanc sur le système de récupération de place JVM si vous êtes vraiment intéressé par la GC. (Tout, il suffit de google JVM Garbage Collection)

J'ai été émerveillé par certaines des techniques utilisées et lors de la lecture de certains concepts tels que "Eden". J'ai vraiment réalisé pour la première fois que Java et la machine virtuelle Java pouvaient battre C / C ++ rapidement. (Chaque fois que C / C ++ libère un objet / un bloc de mémoire, du code est impliqué ... Lorsque Java libère un objet, il ne fait rien du tout; car dans un bon code OO, la plupart des objets sont créés et libérés presque immédiatement, c'est incroyablement efficace.)

Les GC modernes ont tendance à être très efficaces: ils gèrent des objets plus anciens très différemment des nouveaux objets, ils peuvent contrôler les GC de manière concise, longue ou complète, et de nombreuses options de GC peuvent être gérées par des commutateurs de ligne de commande. il est donc utile de savoir à quoi correspondent tous les termes.

Remarque: je viens de me rendre compte que c'était trompeur. L'allocation STACK de C ++ est très rapide - mon propos concernait l'allocation d'objets capables de subsister après la fin de la routine en cours (ce qui, à mon avis, DEVRAIT être tous les objets - vous ne devriez pas avoir à y penser à tout moment. penser en mode OO, mais en vitesse C ++, cela peut rendre cette tâche peu pratique).

Si vous n'allouez que des classes C ++ sur la pile, son allocation sera au moins aussi rapide que celle de Java.

Java collecte tous les objets inaccessibles. Si rien d'autre n'a de référence à l'entrée, elle sera collectée, même si elle est référencée.

oui Java Garbage Collector gère l'auto-référence!

How?

Il existe des objets spéciaux appelés racines de récupération de place (racines GC). Celles-ci sont toujours accessibles, de même que tout objet qui les a à sa propre racine.

Une application Java simple a les racines GC suivantes:

  1. Variables locales dans la méthode principale
  2. Le fil principal
  3. Variables statiques de la classe principale

entrer la description de l'image ici

Pour déterminer quels objets ne sont plus utilisés, la machine virtuelle Java exécute par intermittence ce que l’on appelle très justement un algorithme mark-and-sweep . Cela fonctionne comme suit

  1. L'algorithme parcourt toutes les références d'objet, en commençant par le CPG. racines et marque chaque objet trouvé comme vivant.
  2. Toute la mémoire de tas non occupée par les objets marqués est récupéré. Il est simplement marqué comme libre, essentiellement balayé de objets inutilisés.

Ainsi, si un objet n'est pas accessible depuis les racines du GC (même s'il est auto-référencé ou référencé de manière cyclique), il sera soumis au nettoyage de la mémoire.

Simplement, oui. :)

Découvrez http://www.ibm.com/developerworks/ java / library / j-jtp10283 /

Tous les JDK (de Sun) ont un concept de "capacité à atteindre". Si le GC ne peut pas "atteindre" un objet, il s'en va.

Ce n'est pas un "nouveau" " info (vos premiers interlocuteurs sont formidables) mais le lien est utile et la brièveté est quelque chose de doux. :)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top