Pull to refresh

Comments 14

Видел подобные тесты, которые показывают, что т.н. новый "reflection API" в Java 8 и выше, довольно быстр, что не может не радовать. Но MethodHandle (конкретно в Oracle JDK 8 build 65) вызывал у нас в проекте ошибку OutOfMemory, аналогично ситуации, описанной здесь: https://bugs.openjdk.java.net/browse/JDK-7021343.
Пришлось отказаться от его использования.

Странно всё это. Ошибка по ссылке чисто техническая: возвращается одна ошибка вместо другой, в любом случае сценарий использования неадекватный. Вероятно, у вас ошибка по какому-то другому поводу, не связанная с этим багом. Вообще если вы используете лямбды, вы уже используете методхэндлы.

MethodHandle.invoke, хоть и реализован по-другому, но делает примерно всё то же, что и Method.invoke, за исключением проверок доступа. Поэтому большого выигрыша сами по себе MethodHandles не дают. Чтобы получить максимальную выгоду от java.lang.invoke, имеет смысл MethodHandle преобразовать в экземпляр интерфейса с помощью LambdaMetafactory. И тогда вызов будет столь же быстрым, как и обычный invokeinterface.
реализация на стороне C++ тривиальна
Ой ли? :)

Вся сложность нативной рефлексии скрыта именно внутри JVM кода, чему посвящён целый класс на 1000+ строк кода. Здесь и ресолвинг метода, и преобразование типов, и всевозможные проверки, и перекладывание аргументов. И всё это интерпретируется каждый раз заново для каждого вызова, на что как раз и тратится уйма времени.

Согласен, коряво написал. Я имел в виду, что сам native-метод короткий. Понятно, что эти 200 наносекунд куда-то уходят, значит, где-то есть код, который в это время выполняется, и он не очень короткий.

А что будет в генерированном классе если вызываемый через рефлекшн метод бросает interrupted exception?

Как видно из генерированного кода, абсолютно любое исключение в вызываемом методе обернётся в InvocationTargetException.

Хотя какая разница. Клиент должен это хэндлить.

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

Если нет необходимости, конечно, лучше избегать. Хотя бы ради читаемости кода. Всяко же лучше p.getName(), чем Person.class.getMethod("getName").invoke(p)? :-)


С восьмой джавы некоторые сценарии динамического вызова с рефлекшном можно заменить на ссылки на методы. Скажем, раньше вы куда-то передавали класс и имя метода, который вам должен что-то возвращать: doSomething(Person.class, "getName") и внутри делали вот это всё clazz.getMethod. Теперь это можно заменить на doSomething(Person::getName) (тип аргумента Supplier<String>). Это сделает код более читаемым и быстрым.

Возможно кто-то знает, есть ли для андроида решения вроде MethodHandle, позволяющее избежать генерации вызываемого кода руками?
На сколько я знаю, в андроиде есть поддержка лямбд и ссылок на методы, значит хендлы как то юзаются.
Я детально не в курсе, но вроде 8 Джава поддерживается только в Андроиде 7.0. А лямбды реализованы через анонимные классы.
https://developer.android.com/guide/platform/j8-jack.html
нужно еще новый компилятор юзать
Sign up to leave a comment.

Articles