Удалит ли сборщик мусора внешний объект, если объект внутреннего класса всё ещё используется?

349
18 июня 2017, 15:43

Имеем код:

Iterator<Object> it = new Collection<Object>(){/*...implementation...*/}.iterator();

Вопрос: не удалит ли garbage collector тот объект, который я создал для выражения коллекции? Ведь формально ссылки на этот объект у нас нет, но it (Iterator<Object>) всё-таки связан с внутренностью нашего объекта безымянного класса.

Другими словами, рассмотрим код:

Iterator<Object> it = new Collection<Object>(){             // Строка (1)
    private Object[] array;
    public Iterator<Object> iterator(){
        /*здесь возвращается итератор, ссылающийся на this.array
        + выполняющий свои задачи*/
    } 
    /* + other implementation...*/ 
}.iterator();

Тогда удалится ли GC'ом объект созданный в первой строке, ссылки на который у нас объективно нет? //Строка (1)

Для особо любящих в комментариях писать псевдо-ответы, вот код того, как именно будет выглядеть мой iterator:

Iterator<Object> it = new Collection<Object>() { // Строка (1)
        private Object[] array2;
        @Override
        public Iterator<Object> iterator() {
            return new Iterator<Object>() {
                Object[] array;
                {
                    array = array2;
                }
                @Override
                public boolean hasNext() {
                    // Делаем то, что должны
                    return false;
                }
                @Override
                public Object next() {
                    // Делаем то, что должны
                    return null;
                }
            };
        }
        /* + other implementation... */
}.iterator();
Answer 1

Нет, исходный объект Collection (обозначим его A) не может быть удалён. Причины таковы:

  1. В методе iterator() (который, очевидно, вызывается, когда A ещё жив) создаётся экземпляр анонимного класса (назовём его B). В соответствии с JLS для SE 8, пункт 15.9.5 анонимный класс эквивалентен внутреннему классу (inner class; не путать с вложенным классом - nested class). Это те, что объявляются в классе просто как class, не static class.
  2. Каждый внутренний класс неявно хранит ссылку на тот объект, в котором он был создан. То если если вы создаёте B внутри кода A, то экземпляр B содержит ссылку на объект A. Это верно даже в том случае, если внутри кода B никакого доступа к полям/методам A нет (более подробный ответ на английском SO из 2009 года тут).
  3. А раз свежесозданный B содержит ссылку на A, и эта ссылка сохраняется в переменной it, то пока живёт it, живёт и A.

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

Причина такова: когда вы создаёте внутренний класс

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

READ ALSO
вывод Яндекс карты - много городов

вывод Яндекс карты - много городов

Доброго дня, подсобите советом: на сайте много страниц с разными городами на каждой странице города нужно выводить карту с центрированием...

273
Вертикальное меню на уровне с header

Вертикальное меню на уровне с header

Уже долго ломаю голову, но никак не получается сделать так, чтоб вертикальное меню с лого были на уровне с хедером

339
Как сделать адаптивное меню, в котором бы не сразу все пункты исчезали, а в зависимости от ширины скрывались бы под кнопкой &ldquo;ещё&rdquo;? [требует правки]

Как сделать адаптивное меню, в котором бы не сразу все пункты исчезали, а в зависимости от ширины скрывались бы под кнопкой “ещё”? [требует правки]

Как сделать адаптивное меню, в котором бы не сразу все пункты исчезали, а в зависимости от ширины скрывались бы под кнопкой "ещё"?

232
Отключение шкал значений осей в OxyPlot WPF

Отключение шкал значений осей в OxyPlot WPF

ПриветствуюХотелось бы узнать, каким образом можно отключить шкалы (помечены в красном круге на изображении) на графике

320