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

Почему определение класса как окончательного улучшает производительность JVM?

Цитата из http://sites.google.com/site/gson/gson-design-document:

Почему большинство классов в Gson помечены как Окончательный?

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

Почему это так? [Если бы я догадался: из JVM известно, что класс является окончательным, он не поддерживает таблицы переопределения методов? Есть ли другие причины?]

В чем преимущество производительности?

Это относится к классам, которые являются частотными экземплярами (POJO?) или, возможно, классу, которые являются хранителями статических методов (классы полезности)?

Могут ли методы, определенные как окончательные, теоретически повысить производительность?

Есть ли какие-либо последствия?

Спасибо, Максим.

4b9b3361

Ответ 1

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

Некоторые виртуальные машины (например, HotSpot) могут делать что-то более разумно и знать, когда методы не переопределены и быстрее генерируют более быстрый код.

Здесь - более подробная информация о HotSpot. И еще общая информация.

Ответ 2

Старый, по-видимому, больше не , но в значительной степени, статья об этом от IBM developerWorks, который гласит:

Общее мнение таково: объявление классов или методов final упрощает компилятор для встроенные вызовы методов, но это восприятие неверно (или на по крайней мере, сильно завышена).

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

Также см. этот ответ на другой вопрос. Там также эквивалентный вопрос для .Net, обсуждаемый здесь. SO обсуждение, Являются ли последние методы встроенными? "В вопросе под названием" Какие оптимизации будут бесполезны завтра, "этот список появляется в списке.

Вот кто-то пытается охарактеризовать эффект на вставке HotSpot из статических и конечных классов.

Обратите также внимание на то, что происходит перехват эффектов методов final по сравнению с final. Вы можете получить некоторую выгоду от производительности (опять же, у меня нет хорошей справки) для методов final, так как это может привести к тому, что JIT делает вложение, иначе это не могло бы (или не просто). Вы получаете тот же эффект, когда вы отмечаете класс final, что означает, что все методы также становятся окончательными. Обратите внимание, что люди Sun/Oracle заявляют, что HotSpot обычно может делать это с ключевым словом final или без него. Есть ли дополнительные эффекты от самого класса final?

Для справки, ссылки на JLS на окончательные методы и конечные классы.

Ответ 3

Не зная реализации каждой конкретной JVM, я бы теоретически сказал, что если JVM знает, что указатель на объект является указателем на конечный тип, он может выполнять не виртуальные вызовы функций (т.е. direct vs косвенные) к функциям-членам (т.е. без косвенной привязки через указатель функции), что может привести к более быстрому выполнению. Это также, в свою очередь, может привести к расширению возможностей.

Ответ 4

Маркировка классов как окончательных позволяет применять дальнейшие оптимизации во время этапа JIT.

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

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

Рассмотрим:

A extends B
B extends C

B myInstance = null;
if(someCondition)
   myInstance = new B();
else
   myInstance = new C();
myInstance.toString();

В этом случае JIT не может знать, будет ли вызываться реализация C toString() или реализации B toString(). Однако, если B отмечен как окончательный, для любой реализации, отличной от B, невозможно выполнить правильную реализацию

Ответ 5

Никакой разницы, это просто спекуляция. Единственная ситуация, в которой он имеет смысл, это такие классы, как String и т.д., Где jvm рассматривает их по-разному.