Сборщик мусора в Java - установить объект ноль - PullRequest
19 голосов
/ 17 апреля 2011

Предположим, что существует объект Tree с корневым объектом TreeNode, и каждый TreeNode имеет объекты leftNode и rightNode (например, объект BinaryTree)

Если я позвоню:

myTree = null;

что в действительности происходит со связанными объектами TreeNode внутри дерева? Будет ли сбор мусора, или я должен установить все нулевые связанные объекты внутри объекта дерева?

Ответы [ 6 ]

32 голосов
/ 17 апреля 2011

Сборка мусора в Java выполняется на основе «достижимости». JLS определяет термин следующим образом:

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

Пока объект достижим *, он не подходит для сборки мусора.

JLS оставляет за собой реализацию Java, чтобы выяснить, как определить, доступен ли объект . Если реализация не может быть уверена, она может обрабатывать теоретически недоступный объект как достижимый ... и не собирать его. (Действительно, JLS позволяет реализации не собирать ничего, никогда! Хотя разумная реализация не сделала бы это.)

На практике (консервативная) достижимость рассчитывается путем отслеживания; посмотрим, чего можно достичь, следуя ссылкам, начинающимся с переменных класса (статических) и локальных переменных в стеках потоков.


Вот что это значит для вашего вопроса:

Если я позвоню: myTree = null; что на самом деле происходит со связанными объектами TreeNode внутри дерева? Будет ли сбор мусора, или я должен установить все нулевые связанные объекты внутри объекта дерева ??

Предположим, что myTree содержит последнюю оставшуюся доступную ссылку на корень дерева.

  1. Ничего не происходит немедленно.
  2. Если внутренние узлы ранее были доступны только через корневой узел, то они теперь недоступны и могут быть использованы для сбора мусора. (В этом случае присвоение null ссылкам на внутренние узлы не требуется.)
  3. Однако, если внутренние узлы были доступны через другие пути, они предположительно по-прежнему достижимы и, следовательно, НЕ подходят для сбора мусора. (В этом случае присвоение null ссылкам на внутренние узлы является ошибкой. Вы разбираете структуру данных, которую позже может попытаться использовать что-то другое.)

Если myTree не содержит последнюю оставшуюся доступную доступную ссылку на корень дерева, то обнуление внутренней ссылки является ошибкой по той же причине, что и в 3. выше.


Так когда должны вам null вещи, которые помогут сборщику мусора?

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

  1. Ссылки на объекты в переменных класса ... которые (по определению) никогда не выходят за рамки.
  2. Ссылки на объекты в локальных переменных, которые все еще находятся в области видимости ... но не будут использоваться. Например:

     public List<Pig> pigSquadron(boolean pigsMightFly) {
       List<Pig> airbornePigs = new ArrayList<Pig>();
       while (...) {
         Pig piggy = new Pig();
         ...
         if (pigsMightFly) {
           airbornePigs.add(piggy);
         }
         ...
       }
       return airbornePigs.size() > 0 ? airbornePigs : null;
     }
    

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

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

Следует отметить, что компилятор / среда выполнения могут иногда выяснить, что переменная в области действия фактически мертва. Например:

public void method(...) {
    Object o = ...
    Object p = ...
    while (...) {
        // Do things to 'o' and 'p'
    }
    // No further references to 'o'
    // Do lots more things to 'p'
}

Некоторые Java-компиляторы / среды выполнения могут быть в состоянии обнаружить, что 'o' не нужен после окончания цикла, и обрабатывать переменную как мертвую.


* На самом деле мы говорим о сильной достижимости. Модель достижимости GC более сложна, если учесть мягкие, слабые и фантомные ссылки. Однако они не относятся к сценарию использования OP.

5 голосов
/ 06 февраля 2014

myTree - это просто ссылочная переменная, которая ранее указывала на объект в куче.Теперь вы устанавливаете это в нуль.Если у вас нет другой ссылки на этот объект, тогда этот объект будет иметь право на сборку мусора.

Чтобы сборщик мусора мог удалить объект myTree, просто позвоните gc() после того, как выдля него установлено значение null

myTree=null;
System.gc();

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

4 голосов
/ 17 апреля 2011

Вы не можете установить объект на null, только переменную, которая может содержать указатель / ссылку на этот объект.На сам объект это не влияет.Но если теперь нет путей от какого-либо живого потока (т. Е. Локальной переменной любого запущенного метода) к вашему объекту, он будет собирать мусор, если и когда потребуется память.Это относится к любым объектам, в том числе к тем, на которые ссылается исходный объект дерева.

Обратите внимание, что для локальных переменных обычно не требуется устанавливать их на null, если метод (или блок) завершит работускоро все равно.

4 голосов
/ 17 апреля 2011

Они будут собираться мусором, если у вас нет других ссылок на них (возможно, руководство).Если у вас есть ссылка на дерево, то да, они будут собираться мусором.

1 голос
/ 17 апреля 2011

В Java вам не нужно явно устанавливать объекты в null, чтобы позволить им быть GC'd. Объекты имеют право на сборщик мусора, если на него нет ссылок (игнорируя классы java.lang.ref.*).

0 голосов
/ 17 апреля 2011

Объект собирается, когда на него больше нет ссылок.

В вашем случае будут собраны узлы, на которые непосредственно ссылается объект, на который формально ссылается myTree (корневой узел), и т. Д.

Это, конечно, не такесли у вас есть выдающиеся ссылки на узлы за пределами дерева.Они получат GC'd, как только эти ссылки выйдут за рамки (вместе со всем, на что они только ссылаются)

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