Method handles are implemented in Native Image through reflection. A method handle can have one
of two forms:
- DirectMethodHandle: a method handle that is bound to an actual method. This type of handle
contains a MemberName field which links to the Reflection API representation of the method, and
is used to invoke it.
- BoundMethodHandle: a method handle that links to other method handles. It contains a
LambdaForm, which is a tree of method handle invocations. These invocations can take three types
of arguments: the arguments to the BoundMethodHandle invocation, the results of previous
invocations in the tree, or cached parameters stored in the BoundMethodHandle. The return value
of the handle is usually the result of the last invocation in the tree.
Both types of method handles are created through the API defined in the
java.lang.invoke
package. We mostly reuse the JDK implementation for those, with some exceptions which are
detailed in the substitution methods in this package, notably to avoid the runtime compilation of
method handle trees into optimized invokers.
Some direct method handles with particular semantics (defined in
MethodHandleIntrinsic)
are directly executed without going through the reflection API. We also substitute the native
calls into the JDK internals with equivalent implementations (see
Target_java_lang_invoke_MethodHandleNatives).