Делает ли ссылка объекта нулевой, освобождает память, занятую этим объектом [duplicate]

Вот очень интересное решение вашей проблемы: http://24ways.org/2005/have-your-dom-and-script-it-too

Поэтому используйте это вместо тегов скрипта:

15
задан geo 17 April 2011 в 00:18
поделиться

6 ответов

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

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

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

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

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


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

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

Предположим, что 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 является ложным, то объект списка не будет использоваться. Но никакой основной компилятор 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 / runtimes могут распознавать, что «o» не требуется после окончания цикла и обрабатывает переменную как мертвую.


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

27
ответ дан Stephen C 18 August 2018 в 23:40
поделиться

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

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

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

0
ответ дан Brian Roach 18 August 2018 в 23:40
поделиться
  • 1
    Объект имеет право как GCd, если на нем больше нет ссылок. – Matt Ball 17 April 2011 в 04:49
  • 2
    Если быть точным, да, это правильно. Однако, будучи одинаково педантичным, я могу с уверенностью сказать, что объект не будет быть GC'd, если есть ссылка на него. – Brian Roach 17 April 2011 в 05:03
  • 3
    @BrianRoach - чтобы быть более точным, вы должны перефразировать это, чтобы отличить различия в поведении с различными типами ссылок. – Stephen C 17 July 2012 в 00:26
  • 4
    В любом случае это неверно, потому что нет никакой гарантии, что какая-либо конкретная реализация GC использует подсчет ссылок в качестве критерия удаления. На самом деле, это очень маловероятно из-за утечки круговой ссылки памяти. Самый распространенный метод, который я нашел, - это «отметка и развертка», хотя есть и другие. – user 21 March 2015 в 15:06
  • 5
    @ tgm1024 - Этот ответ не говорит о подсчете ссылок. Если бы это было так, ваша критика была бы правильной ... но это не так. – Stephen C 24 August 2015 в 10:56

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

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

myTree=null;
System.gc();

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

5
ответ дан JavaTechnical 18 August 2018 в 23:40
поделиться

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

1
ответ дан Matt Ball 18 August 2018 в 23:40
поделиться
  • 1
    Я боюсь, что это заявление может ввести в заблуждение, хотя и верно. Объект в массиве никогда не может быть собран в мусор, если вы не установите индекс массива, где он находится в нуле, при условии, что вы все еще используете другие объекты в массиве. Это классическая утечка памяти в массивах. – Edwin Dalorzo 17 April 2011 в 00:37

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

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

4
ответ дан Paŭlo Ebermann 18 August 2018 в 23:40
поделиться
  • 1
    Я считаю, что это критически важная концепция, которую мы, как опытные инженеры, полностью замаскировали. И мы делаем это не потому, что мы этого не понимаем, а потому, что трудно думать в очень младших терминах. Я бы хотел, чтобы первое заявление Пауло повторялось чаще. – user 21 March 2015 в 15:04

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

4
ответ дан Ry- 18 August 2018 в 23:40
поделиться
  • 1
    Нет никакой гарантии, что это будет сбор мусора. Правильнее было бы сказать: «Они будут иметь право на сбор мусора, если ...». – Steve Kuo 17 April 2011 в 07:24
Другие вопросы по тегам:

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