Зачем использовать отражение для доступа к членам класса, когда 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, где доступ проверяется каждый раз, когда вызывается отражающий метод, проверка доступа к дескриптору метода выполняется при создании дескриптора метода.