Сборщик мусора в Java - установить объект ноль

java garbage-collection

23326 просмотра

6 ответа

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

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

myTree = null;

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

Автор: geo Источник Размещён: 12.11.2019 09:48

Ответы (6)


32 плюса

Решение

Сборка мусора в 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;
     }
    

    Выше мы знаем, что если pigsMightFlyfalse, объект списка не будет использоваться. Но ни один из основных 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.

Автор: Stephen C Размещён: 16.04.2011 11:51

5 плюса

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

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

myTree=null;
System.gc();

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

Автор: JavaTechnical Размещён: 05.02.2014 08:01

4 плюса

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

Автор: Ry- Размещён: 16.04.2011 11:19

4 плюса

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

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

Автор: Paŭlo Ebermann Размещён: 16.04.2011 11:36

1 плюс

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

Автор: Matt Ball Размещён: 16.04.2011 11:21

0 плюса

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

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

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

Автор: Brian Roach Размещён: 16.04.2011 11:21
Вопросы из категории :
32x32