Почему определение класса как финального улучшает производительность JVM? - PullRequest
40 голосов
/ 18 октября 2010

Цитирование из http://sites.google.com/site/gson/gson-design-document:

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

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

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

Какое преимущество в производительности?

Применимо ли это к классам с частотой создания экземпляров (POJO?) Или, возможно, к классам, которые содержат статические методы (Utility).классы)?

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

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

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

Ответы [ 5 ]

37 голосов
/ 18 октября 2010

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

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

Здесь - это более конкретная информация о HotSpot. И некоторые общие информация тоже.

18 голосов
/ 18 октября 2010

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

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

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

Также см. Этот связанный ответ на другой вопрос . Есть также эквивалентный вопрос для .Net, обсуждаемый здесь . ТАК обсуждение, " Являются ли заключительные методы встроенными ?" На вопрос « Какие оптимизации будут бесполезны завтра », этот вопрос появляется в списке.

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

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

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

1 голос
/ 18 октября 2010

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

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

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

Рассмотрим:

A extends B
B extends C

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

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

1 голос
/ 18 октября 2010

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

0 голосов
/ 18 октября 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...