Получить MethodHandle из лямбда-объекта

Из java.lang.invoke.LambdaMetafactory:

Рекомендуемый механизм для оценки лямбда-выражений состоит в том, чтобы преобразовать тело лямбда-выражения в метод, вызвать сайт вызова invokedynamic, список статических аргументов которого описывает единственный метод функционального интерфейса и метод реализации с пониженным сахаром, и вернуть объект (объект лямбда), который реализует целевой тип.

И из проверки это, по крайней мере, то, что делает Oracle JDK.

Мой вопрос: для лямбда-объекта есть ли способ найти имя (или дескриптор) метода реализации? В качестве альтернативы, учитывая список методов реализации, есть ли способ определить, какой из них соответствует данному лямбда-объекту?


person OrangeDog    schedule 19.05.2017    source источник
comment
Если вам нужен общий (портативный) способ, который будет работать и завтра, боюсь, это ответ . Все существующие решения либо сильно зависят от реализации, либо ограничены лишь несколькими случаями, либо и то, и другое. Но, возможно, есть решение для вашего конкретного случая использования…   -  person Holger    schedule 19.05.2017
comment
Что ж, ясно, поскольку спецификация даже не требует участия какого-либо дескриптора метода.   -  person OrangeDog    schedule 22.05.2017
comment
Я не собирался прибегать к этой формальности. Принимая во внимание задокументированное сотрудничество между скомпилированным кодом и LambdaMetaFactory (если мы решим скомпилировать исходный код Java в байт-код, используя его), что является сегодняшней практикой, нам все равно приходится признать тот факт, что конкретная реализация JRE LambdaMetaFactory имеет большую свободу. В частности, нет требования, чтобы возвращаемый класс вообще содержал ссылку на целевой метод. Это может быть прокси, только реализующий функциональный интерфейс, делегирующий другому механизм вызова целевого метода.   -  person Holger    schedule 22.05.2017
comment
Другим практическим примером является то, что я помню дискуссии об исключении таких сгенерированных классов из Инструментации, что является для меня причиной не рекомендовать решение для захвата и анализа этих классов с помощью Инструментации, когда я уже знаю, что оно может перестать работать в одном из следующих версии…   -  person Holger    schedule 22.05.2017


Ответы (1)


Вы можете получить доступ к ConstantPool лямбда-класса (т. е. с помощью sun.misc.SharedSecrets.getJavaLangAccess().getConstantPool(class)), а затем выполнить поиск ссылки на метод. Вы должны игнорировать конструктор объекта, а также ссылки на методы автоупаковки/распаковки, оставшаяся ссылка на метод - это метод реализации.

person Nevay    schedule 19.05.2017
comment
Ага, секретные солнцезащитные пакеты - person OrangeDog; 19.05.2017
comment
Конечно, лямбда-объект может быть в точности ссылкой на метод конструктора Object() или одним из методов упаковки/распаковки. Излишне говорить, сколько деталей реализации предполагается при использовании метода… - person Holger; 19.05.2017