Подтвердить что ты не робот

Готово ли java final помочь компилятору создать более эффективный байт-код?

Возможный дубликат:
Использует ли последнее ключевое слово в Java повышение производительности?

Последний модификатор различные последствия в java в зависимости от того, к чему вы его примените. Мне интересно, если это может помочь компилятору создать более эффективный байт-код. Я полагаю, что вопрос углубляется в работу JVM и может быть специфичным для JVM.

Итак, по вашему опыту, какой-либо из следующих поможет компилятору, или вы используете их только для обычных причин Java?

  • Заключительные классы
  • Окончательные методы
  • Заключительные поля
  • Аргументы конечного метода

Спасибо!

EDIT: Спасибо за все ваши ответы! Обратите внимание, что, как предложил @Zohaib, мой вопрос является дубликатом этого. Я не искал достаточно хорошо, прежде чем отправлять сообщения. Я не удаляю его, потому что вы, ребята, внесли хороший вклад, но ответы могут быть объединены. Я позволю системе "голосовать за близкую", если не будет сказано иначе.

4b9b3361

Ответ 1

Байт-коды не являются значительно более или менее эффективными, если вы используете final, потому что компиляторы байт-кода Java обычно мало способствуют оптимизации. Бонус эффективности (если есть) будет в собственном коде, создаваемом компилятором JIT.

Теоретически использование final дает подсказку компилятору JIT, который должен помочь ему оптимизировать. На практике последние компиляторы HotSpot JIT могут сделать лучшую работу, игнорируя ваши намеки. Например, современный JIT-компилятор обычно выполняет глобальный анализ, чтобы выяснить, является ли данный вызов метода вызовом метода leaf в контексте загружаемых в настоящее время классов. Этот анализ более точен, чем могут быть ваши подсказки final, и среда выполнения может даже обнаруживать, когда загружается новый класс, что делает недействительным анализ... и повторяет анализ и создание собственного кода для затронутого кода.

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

UPDATE

Есть несколько исключений из этого (как указано ниже):

  • При определенных обстоятельствах объявление поля как final изменяет способ использования компилятором байт-кода. Я привел один пример выше. Другим является случай с постоянной переменной (JLS 4.12.4), где значение поля static final будет включено в компилятор байт-кода как в текущие классы и другие классы, и это может повлиять на наблюдаемое поведение кода. (Например, обращение к константной переменной НЕ инициирует инициализацию класса. Следовательно, добавление final может изменить порядок инициализации класса.)

  • Можно предположить, что объявление поля или локального параметра как final может разрешить небольшую оптимизацию компилятора JIT, которая иначе не была бы выполнена. Тем не менее, любое поле, которое может быть объявлено как окончательное, также может быть определено для окончательного компилятора JIT. (Просто не ясно, что JIT-компилятор действительно делает это, и влияет ли это на сгенерированный собственный код.)

Однако мой предыдущий совет применяется. Используйте final, чтобы выразить свои намерения дизайна, а не как подсказку оптимизации.

Ответ 2

Этот вопрос уже задан довольно часто, и ответ в целом таков: компилятор может сделать некоторые оптимизации (например, встроенные константы, которые являются конечными статическими полями), но, как правило, вы не должны беспокоиться об этом, поскольку эти достижения производительности могут фактически не быть заметным. Просто используйте ключевое слово final для "нормальных" причин Java (сделайте поля или параметры неизменяемыми, предотвратите подклассирование или переопределение методов).

Ответ 3

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

Другая проблема заключается в том, что JVM постоянно совершенствуется, и трюк, который сделал большую разницу, больше не может применяться. например в Java 5.0 Lock был намного быстрее, чем synchronized, однако в Java 6 разница намного меньше, а synchronized может быть быстрее.

В целом, это хорошая идея сделать ваш код простым, понятным и легко ремонтируемым, и это также приведет к эффективному коду.

Ответ 4

Использование final не дает никаких преимуществ в производительности. Вы должны прибегнуть к JNI по соображениям производительности. Тем не менее, рекомендуется использовать более совершенные JVM, которые сами оптимизируют байт-код (например: встроенная среда выполнения eclipse более эффективна, чем стандартная) и уделять больше внимания вашему коду.