Зачем использовать отражение для доступа к членам класса, когда MethodHandle быстрее?

С выпуском Java 7 пришли MethodHandle, который позволяет пользователю вызывать метод, как если бы он использовал свой базовый байт-код. В частности, MethodHandles.Lookup Класс предоставляет фабричные методы для создания дескрипторов методов для доступа к членам класса:

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

Функционально это более или менее эквивалентно использованию отражения для доступа к тем же членам класса, но дескрипторы метода работают быстрее, чем отражение.

Таким образом, есть ли причина, чтобы по-прежнему использовать функции отражения, такие как Field#get(..) / Method.invoke(..) или эти методы эффективно устарели с введением более быстрых дескрипторов метода?

Обратите внимание, что хотя дескрипторы методов были введены в Java 7, мой вопрос в первую очередь относится к Java 8, в которой они были оптимизированы, чтобы предположительно достичь производительности, приблизительно равной прямым вызовам поля / метода, превосходя возможности отражения.

2 ответа

Решение

Дескрипторы отражения и метода служат разным целям и существуют на разных уровнях абстракции. Вы должны использовать тот, который подходит для проблемы, которую вы решаете.

Reflection - это механизм самоанализа общего назначения, который включает в себя множество функций, отсутствующих в механизме дескриптора метода, таких как перечисление членов класса (Class.getMethods()), проверка характеристик члена, таких как флаги доступности, проверка общих подписей членов и т. д.

Кроме того, отражающие объекты могут свободно обмениваться без предоставления доступа к шари, потому что проверки доступа выполняются при каждом вызове; дескрипторы метода предоставляют шари возможность вызывать. Таким образом, они также имеют различные последствия для безопасности.

Описатели методов - это низкоуровневый механизм поиска, адаптации и вызова методов. Хотя вызов через дескрипторы метода выполняется быстрее, чем через отражение (хотя на сегодняшний день прямой вызов байт-кода все же в целом быстрее, чем вызов дескриптора метода), дескрипторы метода также значительно сложнее использовать, поскольку они не выполняют автоматически адаптацию, ожидаемую пользователями Java (например, преобразование аргумента String в Object), что приводит к ошибкам компоновки.

Библиотека отражений предназначена для основных пользователей Java; Уровень дескриптора метода больше ориентирован на разработчиков языка компиляции и языка исполнения. Выберите инструмент, предназначенный для работы.

Вы должны использовать (и предпочитаете) MethodHandles в Core Reflection API, когда вы можете.

MethodHandles.Lookup доступ говорит (частично),

В отличие от Core Reflection API, где доступ проверяется каждый раз, когда вызывается отражающий метод, проверка доступа к дескриптору метода выполняется при создании дескриптора метода.

Другие вопросы по тегам