web-dev-qa-db-fra.com

Collecteur d'ordures et référence circulaire

Considérez ces deux classes:

public class A
{
     B b;
     public A(B b) { this.b = b; }
}

public class B
{
     A a;
     public B() { this.a =  new A(this); }
}

Si j'ai des classes conçues comme ci-dessus, les objets de ces classes seraient-ils collectés par Garbage Collector (GC)?

Supposons que je fasse ceci:

void f()
{
     B b = new B();
}

Dans cette méthode, je crée une instance de B appelée b, et lorsque la méthode revient, b sort du domaine d'application et le GC doit être en mesure de la collecter, mais s'il devait le collecter, il devrait d'abord collecter a qui est le membre de B, et pour collecter a, il doit collecter b premier qui est le membre de A. Cela devient circulaire. Ma question est donc: une telle référence circulaire va-t-elle empêcher le GC de collecter les objets?

  • Si oui, comment éviter ce problème? Comment pouvons-nous nous assurer que nous n'avons pas de référence circulaire dans notre conception de classe? Existe-t-il un outil (ou une option de compilation) qui nous aide à détecter la référence circulaire?
  • Si non, où et pourquoi utilisons-nous la classe WeakReference ? Quel est son objectif?
59
Nawaz

Le garbage collector .Net peut absolument gérer les références circulaires. La très vue de haut niveau du fonctionnement du ramasse-miettes est ...

  • Commencez avec les objets locaux, statiques et épinglés GC. Aucune de ces informations ne peut être collectée
  • Marquez chaque objet qui peut être atteint en traversant les enfants de ces objets
  • Récupérez tous les objets qui ne sont pas marqués.

Cela permet de recueillir très bien les références circulaires. Tant qu'aucune d'entre elles n'est accessible à partir d'un objet connu pour être irrécouvrable, la référence circulaire est essentiellement hors de propos.

Remarque: je me rends compte que j'ai omis de nombreux détails amusants afin de garder cette réponse simple et directe

87
JaredPar

Non, ce ne sera pas un problème car le GC peut gérer les références circulaires

MSDN dit

Si un groupe d'objets contient des références les uns aux autres, mais qu'aucun de ces objets n'est référencé directement ou indirectement à partir de la pile ou de variables partagées, la récupération de place récupère automatiquement la mémoire.

30
Haris Hasan

Plusieurs réponses ont déjà expliqué que les références circulaires ne sont pas un problème.

Quant aux références faibles - la raison de les utiliser est la mise en cache.

Lorsque GC parcourt les arbres de dépendance des objets, il ignore les références faibles. En d'autres termes, si la seule référence à un objet est faible, ce sera le garbage collection, mais s'il n'y a pas eu de garbage collection entre la création de la référence et votre tentative d'utilisation, vous pouvez toujours accéder à l'objet.

5
mfeingold

Non, cette référence circulaire n'affectera pas le garbage collector, et elle sera parfaitement capable de collecter l'instance de B.

Le garbage collector sait que personne ne peut référencer l'instance de B après être hors de portée, et par conséquent, personne ne peut utiliser l'instance de B pour référencer indirectement A.

5
driis