Финал использования для переменных в Java улучшают сборку "мусора"?

Я бы использовал технологию WebRTC в качестве платформы с открытым исходным кодом для такого приложения.

Официальный сайт

На самом деле это проект с открытым исходным кодом, который поддерживает все необходимые для одноранговых технологий из коробки:

  • ICE и STUN (обход NAT)
  • DTLS и SRTP (безопасность)
  • AVPF для качества потоковой передачи.

82
задан Goran Martinic 21 November 2008 в 09:05
поделиться

9 ответов

Вот немного отличающийся пример, один с заключительными полями ссылочного типа, а не локальными переменными типа окончательного значения:

public class MyClass {

   public final MyOtherObject obj;

}

Каждый раз, когда Вы создаете экземпляр MyClass, Вы будете создавать исходящую ссылку на экземпляр MyOtherObject, и GC должен будет перейти по той ссылке для поиска живых объектов.

JVM использует алгоритм GC развертки метки, который должен исследовать весь живой refereces в "корневых" местоположениях GC (как все объекты в текущем стеке вызовов). Каждый живой объект "отмечен" как являющийся живым, и любой объект, упомянутый живым объектом, также отмечен как являющийся живым.

После завершения фазы метки, GC развертывается через "кучу", освобождая память для всех неотмеченных объектов (и уплотняя память для остающихся живых объектов).

кроме того, важно распознать, что память "кучи" Java делится в "молодое поколение" и "старое поколение". Все объекты первоначально выделяются в молодом поколении (иногда называемый "детским садом"). Так как большинство объектов является недолгим, GC более агрессивен об освобождении недавнего мусора от молодого поколения. Если объект переживает цикл сбора молодого поколения, он перемещен в старое поколение (иногда называемый "штатным поколением"), который обрабатывается менее часто.

Так, первое, что пришло на ум, я собираюсь сказать "нет, 'финал' modifer не помогает GC уменьшить свою рабочую нагрузку".

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

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

при использовании маленьких методов, только с приблизительно дюжиной строк кода, тогда объекты, объявленные в рамках того метода, упадут из объема более быстро, и GC будет в состоянии сделать большую часть своей работы в much-more-efficient молодом поколении. Вы не хотите объекты, перемещаемые в старшее поколение, если не абсолютно необходимо.

83
ответ дан benjismith 5 November 2019 в 16:55
поделиться

Единственная вещь, о которой я могу думать, состоит в том, что компилятор мог бы оптимизировать далеко последние переменные и встроить их как константы в код, таким образом Вы заканчиваете без выделенной памяти.

0
ответ дан Sijin 5 November 2019 в 16:55
поделиться

final на локальных переменных и параметрах не имеет никакого значения в произведенные файлы класса, так не может влиять на производительность во время выполнения. Если класс не имеет никаких подклассов, HotSpot рассматривает тот класс, как будто это является окончательным так или иначе (это может отменить позже, если класс, который повреждает то предположение, загружается). Я верю final на методах, является почти таким же как классы. final на статическом поле может позволить переменной интерпретироваться как "время компиляции, постоянное" и оптимизация, которая будет сделана javac на той основе. final на полях позволяет JVM, некоторая свобода проигнорировать происходит - прежде отношения.

3
ответ дан Tom Hawtin - tackline 5 November 2019 в 16:55
поделиться

Нет, это решительно не верно.

Помнят, что final не означает постоянный, это просто означает, что Вы не можете изменить ссылку.

final MyObject o = new MyObject();
o.setValue("foo"); // Works just fine
o = new MyObject(); // Doesn't work.

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

Final должен считаться полезными метаданными разработчику и не как оптимизация компилятора.

25
ответ дан SCdF 5 November 2019 в 16:55
поделиться

Ну, я не знаю об использовании "заключительного" модификатора в этом случае или его эффекте на GC.

, Но я могу говорить Вам это: Ваше использование Помещенных в коробку значений, а не примитивов (например, дважды вместо двойного) выделит те объекты на "куче", а не стеке, и произведет ненужный мусор, который должен будет очистить GC.

я только использую упакованные примитивы при необходимости существующим API, или когда мне нужны nullable примитивы.

11
ответ дан benjismith 5 November 2019 в 16:55
поделиться

Объявление локальной переменной final не будет влиять на сборку "мусора", это только означает, что Вы не можете изменить переменную. Ваш пример выше не должен компилировать, поскольку Вы изменяете переменную totalWeight, который был отмечен final. С другой стороны, объявление примитива (double вместо Double) final будет позволять той переменной быть встроенной в код вызова, так, чтобы мог вызвать некоторую память и повышение производительности. Это используется, когда у Вас есть много public static final Strings в классе.

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

37
ответ дан Ken Gentle 5 November 2019 в 16:55
поделиться

GC действует на недостижимых судей. Это не имеет никакого отношения к "финалу", который является просто утверждением одноразового присвоения. Действительно ли возможно, что GC некоторого VM может использовать "финал"? Я не вижу как или почему.

3
ответ дан dongilmore 5 November 2019 в 16:55
поделиться

Существует не так известный угловой случай со сборщиками "мусора" поколений. (Поскольку краткое описание прочитало ответ , benjismith для более глубокого понимания прочитал статьи в конце).

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

Теперь, проблема возникает из того, что объекту не позволяют иметь ссылки на младшие объекты. Когда долговечное (старое поколение) объект получает ссылку на новый объект, та ссылка должна быть явно прослежена сборщиком "мусора" (см. статью от IBM на коллектор JVM горячей точки ), на самом деле влияя на производительность GC.

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

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

Статьи:

IBM на сборке "мусора": история , в горячая точка JVM и производительность . Они больше не могут быть полностью допустимыми, поскольку это датируется в 2003/04, но они дают некоторым легким считать понимание GCs.

Sun на Настраивающаяся сборка "мусора"

3
ответ дан Community 5 November 2019 в 16:55
поделиться

Конечные переменные не могут быть изменены после начального присвоения (принудительно выполняется компилятором).

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

Вы должны знать, что final позволяет компилятору делать предположения о том, что следует оптимизировать. Встраивание кода и исключение кода, о котором известно, что он недоступен.

final boolean debug = false;

......

if (debug) {
  System.out.println("DEBUG INFO!");
}

println не будет включен в байтовый код.

5
ответ дан 24 November 2019 в 09:09
поделиться
Другие вопросы по тегам:

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