2017-01-11 9 views
1

Скажем, у меня есть следующие классы, как описано ниже:Циклические ссылки в Java и сборке мусора

class A { 
    private B b; 

    public A { 
     b = new B(this); 
    } 
} 

class B { 
    private C c; 
    private A a; 

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

    public removeRefereceToC() { 
     c = null; 
    } 
} 

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

Если мы посмотрим на график ссылок, А ссылки В (и ссылки B A), ссылки B C (и ссылки C B). Теперь, если бы мы должны были вызвать метод B removeReferenceToC(), то ссылка B на объект C была бы устранена, но C все равно будет ссылаться на B. В этот момент C будет иметь право на сбор мусора?

Причина, по которой я не уверен, что из-за направления ссылок C больше не может быть достигнуто от B, что заставляет меня думать, что C имеет право на сбор мусора, однако тот факт, что C все еще ссылается на B, бросает меня выключили.

Итак, если B отменяет свою ссылку на C, будет ли C иметь право на сбор мусора?

Редактировать: Этот вопрос помечен как дубликат. Я думаю, что основное различие между моим вопросом и ранее задаваемыми вопросами можно суммировать следующим образом: Предыдущие вопросы: A -> B < => C, после чего удаляется ссылка от A до B, оставляя AB < => C

Мой вопрос: < => B < => C, то реф от B до C получает удаляют, оставляя < => B < - C

+0

* «однако тот факт, что C все еще ссылается на B, отбрасывает меня». * Почему?Важно то, что есть ссылки на объект, а не на тот объект, к которому относится этот объект. – Tom

+0

Важно то, может ли объект быть достигнут из корня GC: https://www.dynatrace.com/resources/ebooks/javabook/how-garbage-collection-works/ – Blorgbeard

+0

@Tom Как я об этом думаю заключается в том, что есть стрелка, указывающая от B до C и другая стрелка, указывающая от C до B с каждой стрелкой, указывающей ссылку. Если я отклоняю ссылку B на C, я удаляю стрелку из B в C, но стрелка от C до B все еще остается (но она указывает от C до B). Итак, когда сборщик мусора делает свою вещь, он думает, что C до сих пор доступен из B? Или он видит «стрелку», указывающую от C до B, и понимает, что C недоступен из B? – neonDion

ответ

1

Вы думаете слишком много технических терминов. Сбор мусора определяется как любая мера, способная восстанавливать хранение недоступных объектов.

Java Language Specification §12.6.1 определяет:

достижимы объект любой объект, который можно получить в любой потенциальной продолжения вычислений с любого живого потока.

Ориентированный ссылка является способ, как работает код может получить доступ к объекту, и, по сути, пересекая эти ссылки является типичным способом, как реализации сборщика мусора обнаружить достижимости объектов, но следует подчеркнуть, что даже существование, например локальная переменная, относящаяся к объекту, недостаточна для предотвращения ее сбора мусора, если «потенциальное продолжение вычислений» не читает его.

Это то, что происходит на практике, когда оптимизатор JVM преобразует код, исключая неиспользуемые переменные и мертвый код.

Связанный раздел также четко говорится:

оптимизирующих преобразований программы могут быть разработаны, что уменьшить количество объектов, которые доступны, чтобы быть меньше, чем те, которые бы наивно считать достижимым.

Не отвлекаясь на эти технические детали, достаточно знать, что только возможность доступа к объекту имеет значение, чтобы определить, что это не мусор. Поэтому, независимо от того, как объекты взаимосвязаны с ссылками, если ни один из них не может получить доступ к ним, все они являются мусором.

Смежные вопросы