2012-01-11 5 views
41

Я изучаю новые возможности JDK 1.7, и я просто не могу понять, для чего предназначен MethodHandle? Я понимаю (прямой) вызов статического метода (и использование Core Reflection API, который в этом случае является простым). Я также понимаю (прямой) вызов виртуального метода (нестатического, нефинального) (и использование API Core Reflection, требующего прохождения иерархии класса obj.getClass().getSuperclass()). Вызов не виртуального метода можно рассматривать как частный случай первого.MethodHandle - В чем дело?

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

Но что такое методHandle? API Reflection позволяет вам «просматривать» внутренние объекты без каких-либо предварительных допущений (например, реализованный интерфейс). Вы можете осмотреть объект для какой-либо цели. Но что же такое MethodHandle? Почему и когда я должен его использовать?

ОБНОВЛЕНИЕ: Я читаю сейчас этот http://blog.headius.com/2008/09/first-taste-of-invokedynamic.html артикул. В соответствии с этим главная цель - упростить жизнь для языков сценариев, которые работают поверх JVM, а не для самого языка Java.

ДОПОЛНЕНО-2: я закончу читать по ссылке выше, некоторые цитаты оттуда:

Виртуальная машина Java будет лучшим VM для построения динамических языков, потому что уже есть динамический язык VM. И InvokeDynamic, продвигая динамические языки для первоклассных граждан JVM, докажет это.

Использование отражения для вызова методов отлично работает ... за исключением нескольких проблем. Объекты метода должны извлекаться из определенного типа и не могут быть созданы в общем виде. < ...>

... отраженный вызов намного медленнее, чем прямой вызов. На протяжении многих лет JVM отлично справлялся с тем, чтобы сделать обратный вызов быстрым. Современные JVM на самом деле генерируют кучу кода за кулисами, чтобы избежать значительной части старых JVM. Но простая истина заключается в том, что отраженный доступ через любое количество уровней всегда будет медленнее прямого вызова, частично потому, что полностью генерализованный метод «invoke» должен проверять и повторно проверять тип приемника, типы аргументов, видимость и другие данные, но также потому, что аргументы должны быть объектами (поэтому примитивы получают объект-бокс) и должны быть предоставлены в виде массива для охвата всех возможных явлений (поэтому аргументы получают массив-boxed).

Разница в производительности может не иметь значения для библиотеки, выполняющей несколько отраженных вызовов, особенно если эти вызовы в основном предназначены для динамической настройки статической структуры в памяти, с которой она может выполнять обычные вызовы. Но на динамическом языке, где каждый вызов должен использовать эти механизмы, это серьезный удар по производительности.

http://blog.headius.com/2008/09/first-taste-of-invokedynamic.html

Таким образом, для Java программиста это, по сути бесполезно. Я прав? С этой точки зрения, это можно рассматривать только как альтернативный способ для Core Reflection API.

+0

Нет, абсолютно нет. Эта должность старше 3 лет. Многие разработчики фреймворков внимательно изучают MH и invokedynamic, а также способы их использования, чтобы помочь разработчикам. – kittylyst

+0

Можете ли вы привести пример такого использования? Что можно сделать с MethodHandle, что невозможно сделать с Core Reflection API? – alexsmail

+1

Например, взаимодействие с менеджером безопасности. setAccessible() убьет вас под менеджером безопасности, тогда как механизм Lookup полностью безопасен. Lookup также позволяет создавать MH в контексте, где вы можете его увидеть, а затем передать ссылку на непривилегированные контексты. – kittylyst

ответ

29

Это предшественник Java 8, обеспечивающий языковую поддержку MethodHandles. Вы сможете напрямую обратиться к методу, и MethodHandles будет поддерживать это.

Что вы можете сделать с MethodHandles, это методы карри, изменение типов параметров и изменение их порядка.

Метод Ручки могут обрабатывать как методы, так и поля.

Другой трюк, который делает MethodHandles это использовать примитивные прямой (а не через обертки)

MethodHandles может быть быстрее, чем с помощью отражения, поскольку есть более прямая поддержка в JVM например, они могут быть встраиваемыми. Он использует новую команду invokedynamic.

+6

in Кроме того, stacktraces при выполнении вызова гораздо приятнее, чем с отражением. В качестве недостатка вы не можете вызвать метод handle через отражение (но наоборот) – mihi

+8

'MethodHandle' не использует invokedynamic инструкцию. Но есть отношения другой way: invokedynamic инструкция сильно зависит от 'MethodHandle'. – Holger

+2

@Peter Что именно вы имеете в виду под« Другим трюком, который МетодHandles do использует примитивные прямые (а не через обертки) "? – Geek

10

java.lang.reflect.Method относительно медленный и дорогой с точки зрения памяти. Обработчики методов должны быть «легким» способом прохождения вокруг указателей на функции, которые JVM имеет возможность оптимизировать. С точки зрения методов JDK8 методы не так хорошо оптимизированы, и lambdas, вероятно, будут первоначально реализованы в терминах классов (как внутренние классы).

+0

@tackline, я знаю, что 'java.lang.reflect.Method' относительно медленный. Я также видел некоторую статистику, которая показывает, что' MehodHandle' не является это быстро. Итак, главная причина - производительность. Что делает лямбда в java? Lambda-calculus - совершенно другой подход к программированию ... – alexsmail

+0

@tackline, пожалуйста, посмотрите мое обновление выше. – alexsmail

+0

добавлено еще одно обновление. – alexsmail

7

Think the MethodHandle как современный, более гибкий, более типичный способ отражения.

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

+0

. Это противоречит основной философии Java, чтобы дать только один способ для выполнения задач для Java-программиста. Я знаю, что введение некоторых функций в JDK 1.5 изменило их, но функции в JDK 1.5 были полезны для Java-программиста (ну, я знаю, некоторые из них оспариваются), функция MethodHandle не полезна, насколько я вижу сейчас для обычного Java-разработчика. – alexsmail