Question about Garbage Collection in Java

Suppose I have a doubly linked list. I create it as such:

MyList list = new MyList();

Then I add some nodes, use it and afterwards decide to throw away the old list like this:

list = new MyList();

Since I just created a new list, the nodes inside the old memory area are still pointing to each other. Does that mean the region with the old nodes won't get garbage collected? Do I need to make each node point to null so they're GC'd?

8
задан captain poop 17 August 2010 в 19:43
поделиться

7 ответов

Нет, не знаешь. Java GC отлично справляется с циклическими ссылками.

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

  • Локальные переменные в каждом кадре стека
  • «this» ссылается на каждый кадр стека методов экземпляра
  • Фактически, все статические переменные (на самом деле на них действительно ссылаются объекты Class , на которые, в свою очередь, ссылаются ClassLoader s, но давайте пока проигнорируем это).

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

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

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

12
ответ дан 5 December 2019 в 13:59
поделиться

Если вы создали свой собственный список с двойной связью и поместили в этот список с двойной связью Контейнеры (содержащие элементы из вашего списка); только эти контейнеры связаны друг с другом.

Итак, в вашем списке будет объект A, содержащийся в A '. A 'связан с B', а B 'является контейнером, содержащим B и т. Д. И ни один из объектов не должен ссылаться на другой.

В обычном случае эти контейнеры не будут доступны извне (интересен только контент); поэтому только в вашем списке будут ссылки на ваши контейнеры (помните, что ваш контент не знает о его контейнере).

Если вы удалите последнюю ссылку на свой список (список, а не контейнер или содержимое), GC попытается собрать содержимое вашего списка, ведьма - это ваши контейнеры и ваше содержимое.

Поскольку ваши контейнеры недоступны за пределами единственной ссылки, которая у них есть, это друг друга и основной список. Все это называется островком изоляции . Что касается контента, если у них все еще есть ссылки в вашем приложении, они переживут сборщик мусора, в противном случае - нет.

Итак, когда вы удалите свой список, будут удалены только A 'и B', потому что даже если они все еще имеют ссылки, эти ссылки являются частью острова. Если у A и B больше нет ссылок, они тоже будут удалены.

1
ответ дан 5 December 2019 в 13:59
поделиться

Нет, GC все равно вернет их, поэтому вам не нужно указывать для них значение null. Вот хорошее описание одного абзаца из этой статьи JavaWorld :

Любой алгоритм сборки мусора должен сделать две основные вещи. Во-первых, он должен обнаруживать мусорные объекты. Во-вторых, это должен освободить место в куче, используемое мусорные объекты и сделать это доступно для программы. Мусор обнаружение обычно выполняется путем определения набора корней и определение достижимости из корни. Объект доступен, если есть это некоторый путь ссылок из корни, по которым выполняющаяся программа может получить доступ к объекту. Корни всегда доступен для программы. Любой объекты, доступные из корни считаются живыми. Объекты которые недостижимы считаются мусор, потому что они больше не могут повлиять на будущий ход программы исполнение.

0
ответ дан 5 December 2019 в 13:59
поделиться

Сборщик мусора проверяет, ссылаются ли на объекты живые потоки. Если объекты недоступны для живых потоков, они имеют право на сборку мусора.

Не имеет значения, ссылаются ли объекты друг на друга.

0
ответ дан 5 December 2019 в 13:59
поделиться

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

В статье Википедии о сборке мусора обсуждаются различные способы, которыми это можно сделать, хотя я точно не знаю, какой метод используется какой-либо из реализаций JVM.

0
ответ дан 5 December 2019 в 13:59
поделиться

Сборщик мусора ищет объекты, на которые нигде нет ссылок. Поэтому, если вы создаете объект и теряете ссылку, как в примере, сборщик мусора его соберет.

-1
ответ дан 5 December 2019 в 13:59
поделиться

Нет - Java (по крайней мере, как обычно реализовано) не использует подсчет ссылок, она использует настоящий сборщик мусора. Это означает (по сути), что когда ему не хватает памяти, он смотрит на указатели в стеке, в регистрах и других местах, которые всегда доступны, и «преследует» их, чтобы найти все, что из них доступно.

Указатели в других структурах данных, таких как ваш двусвязный список, просто не имеют значения, если нет внешнего указателя (доступного), ведущего к ним.

0
ответ дан 5 December 2019 в 13:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: