Конечные переменные-члены улучшают сборку мусора?

Этот вопрос является продолжением этого, но требует более конкретного сценария.

Допустим, у нас есть следующий класс:

public class Person {
    private Foot left, right;

    public Person(Foot left, Foot right) {
        this.left = left;
        this.right = right;
    }
}

Мне было интересно, можно ли будет оптимизировать следующий класс с точки зрения GC, если мы превратим его в следующий:

public class Person {
    private final Foot left, right;

    public Person(Foot left, Foot right) {
        this.left = left;
        this.right = right;
    }
}

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

Следовательно, в этом примере означает ли маркировка закрытых переменных-членов final, что код приведет даже к незначительному ускорению сборки мусора (или, возможно, это может быть использовано в качестве точки ускорения)?


person Robert Massaioli    schedule 07.06.2011    source источник
comment
ответы на предыдущий вопрос, кажется, довольно однозначно заявляют ответ как нет - есть ли какая-то часть этих ответов неясна? В остальном этот вопрос звучит почти так же   -  person matt b    schedule 07.06.2011


Ответы (3)


Присвоение полям не вызывает работы сборщика мусора или корректировки счетчика ссылок, поскольку сборщики мусора Java не используют счетчик ссылок (*). Итак, ответ таков: объявление поля как final не повлияет на производительность сборщика мусора. (На этапе отслеживания сборщик должен проверить поле, является ли оно final.

Вполне возможно, что объявление поля final могло бы помочь JIT-компилятору в анализе потока данных и оптимизации выборки из памяти. Однако было бы плохой идеей использовать это как оправдание для изменения полей на final. Если вы собираетесь это сделать, сделайте это из соображений правильности (т.е. чтобы сделать конструкцию безопасной в параллельном контексте) или из стилистических соображений (т.е. чтобы упростить понимание и поддержку кода).

(* Ни одна основная реализация Java не полагается на подсчет ссылок для реализации управления памятью. Теоретически возможно, что кто-то может реализовать JVM, которая использует подсчет ссылок, но общепринято считать, что подсчет ссылок ужасно неэффективен ... не говоря уже о проблемах с параллелизмом, циклами сбора и т. д.)

person Stephen C    schedule 07.06.2011
comment
сделайте это из стилистических соображений Звучит неправильно. Настройка окончательных полей (обычный способ, без отражения) является барьером для памяти, так что `среда выполнения (JVM)` гарантирует, что объект правильно построен, а final field правильно сконструирован перед конструктором, если он завершен. (гарантирует видимость памяти). это очень важно в многопоточных программах. - person Op De Cirkel; 07.06.2011
comment
Ответ был довольно хорошим. TIL, что никакой Java GC, например, не использует подсчет ссылок. Хотя Оп Де Сиркель прав, говоря, что поля final полезны для обеспечения неизменяемого объекта. И я знаю, что поля настроек не запускают сборку мусора, но как насчет того, когда объекту человека где-то еще в кодовой базе установлено значение null и он помечен для сборки мусора. Разве это не значит, что вы тоже можете пометить обе ноги для жатвы? - person Robert Massaioli; 07.06.2011
comment
@Robert Massaioli - нет маркировки для сборки мусора. Единственная отметка - НЕ для вывоза мусора. AFAIK, здесь нет возможности для оптимизации. - person Stephen C; 07.06.2011
comment
Тогда ладно. Спасибо за исчерпывающий ответ и маркировку как таковую. - person Robert Massaioli; 07.06.2011

Единственная причина, по которой оптимизация сборщика мусора невозможна, заключается в том, что спецификация JVM действительно позволяет изменять поле final.
final поля имеют особую семантику во время процесса построения объекта, что важно для правильной работы процесса построения в отношении модели памяти java. Но вы можете нарушить правила и изменить их с помощью отражения. В этом случае вы не можете полагаться на семантику поля final (относительно модели памяти java)

забастовка: извините, ребята, я не понимаю, о чем говорю. final не имеет отношения к GC. даже если final вообще нельзя изменить, GC не может получить никакой полезной информации об этом факте

person Op De Cirkel    schedule 07.06.2011
comment
это гипотетически. Предполагается, что будет некоторая оптимизация на основе final полей ... что неверно. - person Stephen C; 07.06.2011

Сборка мусора Java не работает путем подсчета ссылок. Он работает, исследуя объекты на достижимость.

person user207421    schedule 07.06.2011
comment
Сборка мусора не работает при проверке объектов на предмет ссылок Как же тогда может работать? - person Op De Cirkel; 07.06.2011
comment
@Stephen C @Op De Cirkel Спасибо, текст изменен. - person user207421; 07.06.2011