Как предотвратить циркулярные ссылки с помощью внедрения зависимостей и сбора мусора? - PullRequest
1 голос
/ 26 мая 2011

Я думаю, что все еще пытаюсь понять Dependency Injection и роль DI-контейнера.

Если DI означает, что компонент более низкого уровня зависит от компонента более высокого уровня, а циклическая ссылка отсутствует, не будет ли этот объект собирать мусор? Как я вижу, сборщик мусора (mark-and-sweep) хранит только те объекты, которые можно отследить с помощью цепочки ссылок, начиная с корня программы.

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

Моя оригинальная интерпретация DI

Контейнер DI внедряет компоненты со своими обязательными ссылками, и каждый из них хранит ссылку на свою следующую команду с наивысшим значением в команде. Главный класс не может добраться до них, поэтому они должны быть собраны мусором. DI Container does NOT store references to its components

Мое пересмотр DI

Контейнер DI внедряет компоненты с их обязательными ссылками, а также поддерживает ссылку на каждый из них. Каждый из них хранит ссылку на свою следующую команду. Класс Main может связаться с любым из них через DI-контейнер, поэтому они не должны собираться мусором. DI Container DOES store references to its components

Ответы [ 2 ]

5 голосов
/ 26 мая 2011

Трудно понять, что вы на самом деле спрашиваете:

  • Во всех основных реализациях Java есть сборщики мусора, которые могут собирать мусор с помощью циклических ссылок ... или как их чаще называют, справочные циклы.Поэтому нет особой причины избегать циклов ссылок в DI с точки зрения ГХ.

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

  • Явно объявленные зависимости сообщают каркасу DI, что некоторые объекты должны быть построены и подключены раньше других.Они не говорят, что нужно связать с чем, и есть или нет референтные циклы (на уровне Java).


@ Ответ JonnyReeve гласит:

"В общем, ссылка (объект) будет иметь право на сборку мусора только при отсутствии нулевых ссылок (например, вы не можете получить к ней программный доступ)"

Этовводит в заблуждение.Очевидно, что объект, который содержит ссылку на себя, имеет (по крайней мере) одну оставшуюся ссылку, однако, если это единственная существующая ссылка, объект, тем не менее, пригоден для сборки мусора.

Фактически, объект является приемлемымдля сбора, если он не достижим .Для Java это определяется (JLS 12.6.1) следующим образом:

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

Обратите внимание на то, как это сформулировано.Это означает, что объект можно собирать, в то время как локальные переменные все еще ссылаются на него ... при условии, что JVM может сказать, что никакие будущие вычисления не получат доступ к объекту.

1 голос
/ 26 мая 2011

Сборка мусора в AVM - довольно большая тема; Вместо того, чтобы пытаться перейти к более тонким пунктам, я бы предложил начать с чтения статьи Гранта Скиннера о Управление ресурсами .

ответить на ваш вопрос по поводу ссылок; шире говоря, ссылка (объект) будет иметь право на сборку мусора только при отсутствии нулевых ссылок (например: вы не можете программно получить к ней доступ); часто это достигается простым обнулением ссылки; например:

public class Client {
    private var myFoo : Foo;

    public function Client() {
        // myFoo will count as a reference; it will not be 'swept'
        myFoo = new Foo();

        // Business as usual.
        myFoo.bar();
    }

    public function destroy() : void {
        // Remove the reference to myFoo, it can now be 'swept' as no other
        // references remain to it and there is no way to access it.
        myFoo = null;

        // This will trip a Null Reference Error because myFoo is no longer a
        // reference to the 'Foo' instance.
        myFoo.bar();
    }
}
...