Эффективность кастинга на разных уровнях при отбрасывании

Предположим, что у нас есть три (или более) класса

открытый класс A {}

открытый класс B расширяет A {}

открытый класс C расширяет B реализует G {}

Предположим, что у каждого класса есть свои 20 (или более) методов.

Является ли листинг на C против литья на A, оказывает большее влияние на производительность? Как работает Java-кастинг под капотом?

Нужно ли проверять все методы и поля для присутствия путем отражения при отбрасывании?

Edit: Увеличивает ли размер классов (количество полей и методов) производительность при кастинге? Меня интересуют как OpenJRE, так и Dalvik.

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

Ответ 1

Производительность кастинга зависит от реализации JVM.

JLS 5.5 определяет только требования к кастингу (включая рекурсивный алгоритм), но не устанавливает никаких требований к реализации. Фактически правила правил выполнения в 5.5.3 также определяются одинаково. Все реализации JVM, которые дают тот же результат, что и предлагаемый алгоритм, принимаются как надлежащая JVM.

Как правило, отбрасывание до C занимает немного больше времени, так как JVM должен проверять тип среды выполнения объекта. При отбрасывании до A у него нет причин делать одну и ту же проверку, так как B extends A.

Собственно, JVM не заботится о количестве методов и полей. Он сравнивает только иерархию типов, то же самое можно рассмотреть с помощью отражения (o.getClass())

Я сделал пример кода следующим образом: один downcast, затем upcast:

Object o = new Integer(1);
Integer i = (Integer) o;

Object o2 = i;

Скомпилированный байт-код выглядит следующим образом:

 0  new java.lang.Integer [16]
 3  dup
 4  iconst_1       <-- 1 as a parameter to the constructor
 5  invokespecial java.lang.Integer(int) [18]   <-- constructor
 8  astore_1 [o]       <-- store in 'o'
 9  aload_1 [o]
10  checkcast java.lang.Integer [16]    <-- DOWNCAST CHECK, SPECIAL BYTECODE
13  astore_2 [i]
14  aload_2 [i]
15  astore_3 [o2]   <-- WITH UPCAST NO CHECK

Итак, существует специальная инструкция JVM, которая проверяет элемент в верхней части стека с данным классом.

С повышением, проверка вообще отсутствует.

Размер классов (количество полей, методов, фактический размер) не имеет значения, потому что кастинг проверяет Class (метаданные, которые на самом деле являются объектами).

Количество уровней иерархии и число, если реализованы интерфейсы (при переходе на интерфейс) имеет значение, потому что это проверенное дерево наследования/реализации.

Я был бы удивлен, если бы для этой проверки не было какого-то кеша.

Ответ 2

Для подробной архитектуры checkcast (которая упоминалась в другом ответе как механизм JVM для downcasting) в HotSpot, посмотрите на этот документ конференции:

Быстрая проверка подтипа в JVM HotSpot

Цитата из тезисов:

В реальных тестах эта техника выполняет полный подтип проверяет в 3-х инструкциях (только 1 ссылка на память), по существу, все время. В редких случаях он возвращается к более медленному сканированию массива. Память использование умеренное (6 слов на класс) и может быть продано вовремя.

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