Рассмотрим эти два класса:мусора коллектора и циклическая ссылка
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
? В чем его цель?
Посмотрите здесь http://stackoverflow.com/questions/400706/circular-references-cause-memory-leak –
По крайней мере, логически одна из ссылок всегда будет слабой: в вашем примере, cleary 'A 'не может зависеть от' B', потому что 'A' должен быть сделан первым, как член' B', и поэтому 'A' может содержать только слабую ссылку на' B'. Таким образом, безопасно уничтожать «B» сначала, а затем «A». Рассуждая рекурсивно, каждая компьютерная программа должна быть таким образом. Никогда не может быть * истинной *, полностью симметричной круговой зависимости. –
@ KerrekSB: Я согласен с этой логикой. Но это рассматривается с точки зрения творения. Будет ли GC анализировать это (т. Е. Код в каждом методе таких классов, ведь только тогда он может достичь этого вывода)? Я имею в виду, если вы видите объекты после их создания, то это выглядит очень проблематично. – Nawaz