Поддерживает ли Java оптимизацию вызовов методов через интерфейс, который имеет один вариант реализации, обозначенный как final?

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

Однако, что, если у меня есть ссылка на интерфейс, и интерфейс в настоящее время имеет только один разработчик, и что разработчик является окончательным или метод является окончательным в этом разработчике, может ли JVM определить, что во время выполнения и оптимизировать эти вызовы?

Ответ 1

(Вставьте цитату Кнута здесь об оптимизации.)

См. Wikis Home > Внутренние ссылки HotSpot для OpenJDK > PerformanceTechniques.

  • Часто используются методы. Это увеличивает "горизонт" компилятора оптимизация.
  • Статические, частные, окончательные и/или специальные вызовы рядный.
  • Виртуальные (и интерфейсные) вызовы часто понижаются до "специальных" invocations, если иерархия классов разрешает это. Зарегистрирована зависимость в случае, если дополнительная загрузка классов портит вещи.
  • Виртуальные (и интерфейсные) вызовы с однотипным профилем типа с оптимистичной проверкой пользу исторически общего типа (или двух типов).

Есть несколько интересных ссылок из Inlining.

Ответ 2

AFAIK, JVM может выполнять до двух методов, методы не обязательно должны быть окончательными. Он может это сделать, если методы малы и часто вызываются. Если ваш код вызывает три или более метода, будут вызываться только наиболее часто вызываемые методы.

Примечание 1: JVM действительно заботится о том, сколько реализаций существует, только то, сколько фактически вызвано.

Примечание 2: JVM может встроить методы, которых не было во время компиляции, что имеет значение только для кода, доступного во время выполнения.

Ответ 3

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

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

У меня нет ссылки на статью об этом, но я прочитал ее несколько недель назад (и, возможно, ее просто на Java 7, как это).

Ответ 4

JIT-компилятор не может этого сделать, так как довольно часто создается прокси для интерфейсов во время выполнения, поэтому JIT-компилятор никогда не может быть уверен, что не будет динамического прокси-сервера, который реализует определенный интерфейс.