Вопрос о сборке мусора в Java - PullRequest
8 голосов
/ 17 августа 2010

Предположим, у меня есть двусвязный список. Я создаю это так:

MyList list = new MyList();

Затем я добавляю несколько узлов, использую их и после этого решаю выбросить старый список, например:

list = new MyList();

Поскольку я только что создал новый список, узлы внутри старой области памяти по-прежнему указывают друг на друга. Означает ли это, что область со старыми узлами не будет собирать мусор? Мне нужно, чтобы каждый узел указывал на ноль, чтобы они были GC'd?

Ответы [ 7 ]

12 голосов
/ 17 августа 2010

Нет, нет.Java GC прекрасно обрабатывает циклические ссылки.

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

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

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

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

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

1 голос
/ 18 августа 2010

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

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

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

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

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

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

0 голосов
/ 18 августа 2010

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

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

0 голосов
/ 17 августа 2010

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

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

0 голосов
/ 17 августа 2010

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

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

0 голосов
/ 17 августа 2010

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

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

0 голосов
/ 17 августа 2010

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

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