web-dev-qa-db-ja.com

ガベージコレクターと循環参照

次の2つのクラスを検討してください。

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

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

上記のように設計されたクラスがある場合、そのようなクラスのオブジェクトはガベージコレクター(GC)によって収集されますか?

私がこれを行うと仮定します:

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

このメソッドでは、Bと呼ばれるbのインスタンスを作成します。メソッドが戻ると、bはスコープ外になり、GCがそれを収集できるはずです。しかし、それを収集する場合、aのメンバーであるBを最初に収集し、aを収集するには、b最初にAのメンバーです。円形になります。だから私の質問は:そのような循環参照はGCがオブジェクトを収集するのを妨げますか?

  • はいの場合、どうすればこの問題を回避できますか?クラス設計に循環参照がないことをどのように確認できますか?循環参照の検出に役立つツール(またはコンパイラオプション)はありますか?
  • いいえの場合、どこで、なぜ WeakReference クラスを使用するのですか?その目的は何ですか?
59
Nawaz

.Netガベージコレクターは、循環参照を完全に処理できます。 veryガベージコレクタがどのように機能するかについての高レベルのビューは...

  • ローカル、静的、GCピン留めオブジェクトから始めます。これらはどれも収集できません
  • これらのオブジェクトの子をたどることによって到達できるすべてのオブジェクトをマークします
  • マークされていないすべてのオブジェクトを収集します。

これにより、循環参照を問題なく収集できます。収集できないことがわかっているオブジェクトから到達できない限り、循環参照は本質的に無関係です。

注:この答えをシンプルかつ直接的に保つために、私は多くの楽しい詳細を省略していることに気づきました

87
JaredPar

いいえ、GCは循環参照を処理できるため、これは問題にはなりません

MSDNは言う

オブジェクトのグループに相互参照が含まれているが、これらのオブジェクトがスタックまたは共有変数から直接または間接的に参照されていない場合、ガベージコレクションは自動的にメモリを再利用します。

30
Haris Hasan

いくつかの回答は、循環参照は問題ではないことをすでに説明しています。

弱参照について-それらを使用する理由はキャッシュです。

GCがオブジェクトの依存関係ツリーを歩くとき、彼は弱い参照を無視します。言い換えると、オブジェクトへの唯一の参照が弱いものである場合、そのオブジェクトはガベージコレクションされますが、参照の作成と使用の試行の間にガベージコレクションがなかった場合でも、オブジェクトにアクセスできます。

5
mfeingold

いいえ、その循環参照はガベージコレクターに影響を与えず、Bのインスタンスを完全に収集できます。

ガベージコレクターは、スコープの外に出た後は誰もBのインスタンスを参照できないことを知っているため、Bのインスタンスを使用してAを間接的に参照することはできません。

5
driis