A CallSite is a holder for a variable MethodHandle, which is called its target. An invokedynamic instruction linked to a CallSite delegates all calls to the site's current target. A CallSite may be associated with several invokedynamic instructions, or it may be "free floating", associated with none. In any case, it may be invoked through an associated method handle called its dynamic invoker.
CallSite is an abstract class which does not allow direct subclassing by users. It has three immediate, concrete subclasses that may be either instantiated or subclassed.
If a mutable target is not required, an invokedynamic instruction may be permanently bound by means of a java.lang.invoke.constant call site. If a mutable target is required which has volatile variable semantics, because updates to the target must be immediately and reliably witnessed by other threads, a java.lang.invoke.volatile call site may be used. Otherwise, if a mutable target is required, a java.lang.invoke.mutable call site may be used.
A non-constant call site may be relinked by changing its target. The new target must have the same type as the previous target. Thus, though a call site can be relinked to a series of successive targets, it cannot change its type.
Here is a sample use of call sites and bootstrap methods which links every dynamic call site to print its arguments:
static void test() throws Throwable { // THE FOLLOWING LINE IS PSEUDOCODE FOR A JVM INSTRUCTION InvokeDynamic[#bootstrapDynamic].baz("baz arg", 2, 3.14); } private static void printArgs(Object... args) { System.out.println(java.util.Arrays.deepToString(args)); } private static final MethodHandle printArgs; static { MethodHandles.Lookup lookup = MethodHandles.lookup(); Class thisClass = lookup.lookupClass(); // (who am I?) printArgs = lookup.findStatic(thisClass, "printArgs", MethodType.methodType(void.class, Object[].class)); } private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String name, MethodType type) { // ignore caller and name, but match the type: return new ConstantCallSite(printArgs.asType(type)); }
A CallSite is a holder for a variable MethodHandle, which is called its target. An invokedynamic instruction linked to a CallSite delegates all calls to the site's current target. A CallSite may be associated with several invokedynamic instructions, or it may be "free floating", associated with none. In any case, it may be invoked through an associated method handle called its dynamic invoker. CallSite is an abstract class which does not allow direct subclassing by users. It has three immediate, concrete subclasses that may be either instantiated or subclassed. If a mutable target is not required, an invokedynamic instruction may be permanently bound by means of a java.lang.invoke.constant call site. If a mutable target is required which has volatile variable semantics, because updates to the target must be immediately and reliably witnessed by other threads, a java.lang.invoke.volatile call site may be used. Otherwise, if a mutable target is required, a java.lang.invoke.mutable call site may be used. A non-constant call site may be relinked by changing its target. The new target must have the same type as the previous target. Thus, though a call site can be relinked to a series of successive targets, it cannot change its type. Here is a sample use of call sites and bootstrap methods which links every dynamic call site to print its arguments: static void test() throws Throwable { // THE FOLLOWING LINE IS PSEUDOCODE FOR A JVM INSTRUCTION InvokeDynamic[#bootstrapDynamic].baz("baz arg", 2, 3.14); } private static void printArgs(Object... args) { System.out.println(java.util.Arrays.deepToString(args)); } private static final MethodHandle printArgs; static { MethodHandles.Lookup lookup = MethodHandles.lookup(); Class thisClass = lookup.lookupClass(); // (who am I?) printArgs = lookup.findStatic(thisClass, "printArgs", MethodType.methodType(void.class, Object[].class)); } private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String name, MethodType type) { // ignore caller and name, but match the type: return new ConstantCallSite(printArgs.asType(type)); }
A ConstantCallSite is a CallSite whose target is permanent, and can never be changed. An invokedynamic instruction linked to a ConstantCallSite is permanently bound to the call site's target.
A ConstantCallSite is a CallSite whose target is permanent, and can never be changed. An invokedynamic instruction linked to a ConstantCallSite is permanently bound to the call site's target.
No vars found in this namespace.
LambdaConversionException
LambdaConversionException
Methods to facilitate the creation of simple "function objects" that implement one or more interfaces by delegation to a provided MethodHandle, possibly after type adaptation and partial evaluation of arguments. These methods are typically used as bootstrap methods for invokedynamic call sites, to support the lambda expression and method reference expression features of the Java Programming Language.
Indirect access to the behavior specified by the provided MethodHandle proceeds in order through three phases:
Linkage occurs when the methods in this class are invoked.
They take as arguments an interface to be implemented (typically a
functional interface, one with a single abstract method), a
name and signature of a method from that interface to be implemented, a
method handle describing the desired implementation behavior
for that method, and possibly other additional metadata, and produce a
CallSite whose target can be used to create suitable function
objects. Linkage may involve dynamically loading a new class that
implements the target interface. The CallSite can be considered a
"factory" for function objects and so these linkage methods are referred
to as "metafactories".
Capture occurs when the CallSite's target is
invoked, typically through an invokedynamic call site,
producing a function object. This may occur many times for
a single factory CallSite. Capture may involve allocation of a
new function object, or may return an existing function object. The
behavior MethodHandle may have additional parameters beyond those
of the specified interface method; these are referred to as captured
parameters, which must be provided as arguments to the
CallSite target, and which may be early-bound to the behavior
MethodHandle. The number of captured parameters and their types
are determined during linkage.
Invocation occurs when an implemented interface method
is invoked on a function object. This may occur many times for a single
function object. The method referenced by the behavior MethodHandle
is invoked with the captured arguments and any additional arguments
provided on invocation, as if by MethodHandle.invoke(Object...).
It is sometimes useful to restrict the set of inputs or results permitted at invocation. For example, when the generic interface Predicate<T> is parameterized as Predicate<String>, the input must be a String, even though the method to implement allows any Object. At linkage time, an additional MethodType parameter describes the "instantiated" method type; on invocation, the arguments and eventual result are checked against this MethodType.
This class provides two forms of linkage methods: a standard version (metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)) using an optimized protocol, and an alternate version altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)). The alternate version is a generalization of the standard version, providing additional control over the behavior of the generated function objects via flags and additional arguments. The alternate version adds the ability to manage the following attributes of function objects:
Bridging. It is sometimes useful to implement multiple
variations of the method signature, involving argument or return type
adaptation. This occurs when multiple distinct VM signatures for a method
are logically considered to be the same method by the language. The
flag FLAG_BRIDGES indicates that a list of additional
MethodTypes will be provided, each of which will be implemented
by the resulting function object. These methods will share the same
name and instantiated type.
Multiple interfaces. If needed, more than one interface
can be implemented by the function object. (These additional interfaces
are typically marker interfaces with no methods.) The flag FLAG_MARKERS
indicates that a list of additional interfaces will be provided, each of
which should be implemented by the resulting function object.
Serializability. The generated function objects do not
generally support serialization. If desired, FLAG_SERIALIZABLE
can be used to indicate that the function objects should be serializable.
Serializable function objects will use, as their serialized form,
instances of the class SerializedLambda, which requires additional
assistance from the capturing class (the class described by the
MethodHandles.Lookup parameter caller); see
SerializedLambda for details.
Assume the linkage arguments are as follows:
invokedType (describing the CallSite signature) has
K parameters of types (D1..Dk) and return type Rd;
samMethodType (describing the implemented method type) has N
parameters, of types (U1..Un) and return type Ru;
implMethod (the MethodHandle providing the
implementation has M parameters, of types (A1..Am) and return type Ra
(if the method describes an instance method, the method type of this
method handle already includes an extra first argument corresponding to
the receiver);
instantiatedMethodType (allowing restrictions on invocation)
has N parameters, of types (T1..Tn) and return type Rt.
Then the following linkage invariants must hold:
Rd is an interface
implMethod is a direct method handle
samMethodType and instantiatedMethodType have the same
arity N, and for i=1..N, Ti and Ui are the same type, or Ti and Ui are
both reference types and Ti is a subtype of Ui
Either Rt and Ru are the same type, or both are reference types and
Rt is a subtype of Ru
K N = M
For i=1..K, Di = Ai
For i=1..N, Ti is adaptable to Aj, where j=i+k
The return type Rt is void, or the return type Ra is not void and is
adaptable to Rt
Further, at capture time, if implMethod corresponds to an instance method, and there are any capture arguments (K > 0), then the first capture argument (corresponding to the receiver) must be non-null.
A type Q is considered adaptable to S as follows:
QSLink-time checksInvocation-time checks
PrimitivePrimitive
Q can be converted to S via a primitive widening conversion
None
PrimitiveReference
S is a supertype of the Wrapper(Q)
Cast from Wrapper(Q) to S
ReferencePrimitive
for parameter types: Q is a primitive wrapper and Primitive(Q)
can be widened to S
for return types: If Q is a primitive wrapper, check that
Primitive(Q) can be widened to S
If Q is not a primitive wrapper, cast Q to the base Wrapper(S);
for example Number for numeric types
ReferenceReference
for parameter types: S is a supertype of Q
for return types: none
Cast from Q to S
Methods to facilitate the creation of simple "function objects" that implement one or more interfaces by delegation to a provided MethodHandle, possibly after type adaptation and partial evaluation of arguments. These methods are typically used as bootstrap methods for invokedynamic call sites, to support the lambda expression and method reference expression features of the Java Programming Language. Indirect access to the behavior specified by the provided MethodHandle proceeds in order through three phases: Linkage occurs when the methods in this class are invoked. They take as arguments an interface to be implemented (typically a functional interface, one with a single abstract method), a name and signature of a method from that interface to be implemented, a method handle describing the desired implementation behavior for that method, and possibly other additional metadata, and produce a CallSite whose target can be used to create suitable function objects. Linkage may involve dynamically loading a new class that implements the target interface. The CallSite can be considered a "factory" for function objects and so these linkage methods are referred to as "metafactories". Capture occurs when the CallSite's target is invoked, typically through an invokedynamic call site, producing a function object. This may occur many times for a single factory CallSite. Capture may involve allocation of a new function object, or may return an existing function object. The behavior MethodHandle may have additional parameters beyond those of the specified interface method; these are referred to as captured parameters, which must be provided as arguments to the CallSite target, and which may be early-bound to the behavior MethodHandle. The number of captured parameters and their types are determined during linkage. Invocation occurs when an implemented interface method is invoked on a function object. This may occur many times for a single function object. The method referenced by the behavior MethodHandle is invoked with the captured arguments and any additional arguments provided on invocation, as if by MethodHandle.invoke(Object...). It is sometimes useful to restrict the set of inputs or results permitted at invocation. For example, when the generic interface Predicate<T> is parameterized as Predicate<String>, the input must be a String, even though the method to implement allows any Object. At linkage time, an additional MethodType parameter describes the "instantiated" method type; on invocation, the arguments and eventual result are checked against this MethodType. This class provides two forms of linkage methods: a standard version (metafactory(MethodHandles.Lookup, String, MethodType, MethodType, MethodHandle, MethodType)) using an optimized protocol, and an alternate version altMetafactory(MethodHandles.Lookup, String, MethodType, Object...)). The alternate version is a generalization of the standard version, providing additional control over the behavior of the generated function objects via flags and additional arguments. The alternate version adds the ability to manage the following attributes of function objects: Bridging. It is sometimes useful to implement multiple variations of the method signature, involving argument or return type adaptation. This occurs when multiple distinct VM signatures for a method are logically considered to be the same method by the language. The flag FLAG_BRIDGES indicates that a list of additional MethodTypes will be provided, each of which will be implemented by the resulting function object. These methods will share the same name and instantiated type. Multiple interfaces. If needed, more than one interface can be implemented by the function object. (These additional interfaces are typically marker interfaces with no methods.) The flag FLAG_MARKERS indicates that a list of additional interfaces will be provided, each of which should be implemented by the resulting function object. Serializability. The generated function objects do not generally support serialization. If desired, FLAG_SERIALIZABLE can be used to indicate that the function objects should be serializable. Serializable function objects will use, as their serialized form, instances of the class SerializedLambda, which requires additional assistance from the capturing class (the class described by the MethodHandles.Lookup parameter caller); see SerializedLambda for details. Assume the linkage arguments are as follows: invokedType (describing the CallSite signature) has K parameters of types (D1..Dk) and return type Rd; samMethodType (describing the implemented method type) has N parameters, of types (U1..Un) and return type Ru; implMethod (the MethodHandle providing the implementation has M parameters, of types (A1..Am) and return type Ra (if the method describes an instance method, the method type of this method handle already includes an extra first argument corresponding to the receiver); instantiatedMethodType (allowing restrictions on invocation) has N parameters, of types (T1..Tn) and return type Rt. Then the following linkage invariants must hold: Rd is an interface implMethod is a direct method handle samMethodType and instantiatedMethodType have the same arity N, and for i=1..N, Ti and Ui are the same type, or Ti and Ui are both reference types and Ti is a subtype of Ui Either Rt and Ru are the same type, or both are reference types and Rt is a subtype of Ru K N = M For i=1..K, Di = Ai For i=1..N, Ti is adaptable to Aj, where j=i+k The return type Rt is void, or the return type Ra is not void and is adaptable to Rt Further, at capture time, if implMethod corresponds to an instance method, and there are any capture arguments (K > 0), then the first capture argument (corresponding to the receiver) must be non-null. A type Q is considered adaptable to S as follows: QSLink-time checksInvocation-time checks PrimitivePrimitive Q can be converted to S via a primitive widening conversion None PrimitiveReference S is a supertype of the Wrapper(Q) Cast from Wrapper(Q) to S ReferencePrimitive for parameter types: Q is a primitive wrapper and Primitive(Q) can be widened to S for return types: If Q is a primitive wrapper, check that Primitive(Q) can be widened to S If Q is not a primitive wrapper, cast Q to the base Wrapper(S); for example Number for numeric types ReferenceReference for parameter types: S is a supertype of Q for return types: none Cast from Q to S
A method handle is a typed, directly executable reference to an underlying method, constructor, field, or similar low-level operation, with optional transformations of arguments or return values. These transformations are quite general, and include such patterns as conversion, insertion, deletion, and substitution.
Method handle contents Method handles are dynamically and strongly typed according to their parameter and return types. They are not distinguished by the name or the defining class of their underlying methods. A method handle must be invoked using a symbolic type descriptor which matches the method handle's own type descriptor.
Every method handle reports its type descriptor via the type accessor. This type descriptor is a MethodType object, whose structure is a series of classes, one of which is the return type of the method (or void.class if none).
A method handle's type controls the types of invocations it accepts, and the kinds of transformations that apply to it.
A method handle contains a pair of special invoker methods called invokeExact and invoke. Both invoker methods provide direct access to the method handle's underlying method, constructor, field, or other operation, as modified by transformations of arguments and return values. Both invokers accept calls which exactly match the method handle's own type. The plain, inexact invoker also accepts a range of other call types.
Method handles are immutable and have no visible state. Of course, they can be bound to underlying methods or data which exhibit state. With respect to the Java Memory Model, any method handle will behave as if all of its (internal) fields are final variables. This means that any method handle made visible to the application will always be fully formed. This is true even if the method handle is published through a shared variable in a data race.
Method handles cannot be subclassed by the user. Implementations may (or may not) create internal subclasses of MethodHandle which may be visible via the Object.getClass operation. The programmer should not draw conclusions about a method handle from its specific class, as the method handle class hierarchy (if any) may change from time to time or across implementations from different vendors.
Method handle compilation A Java method call expression naming invokeExact or invoke can invoke a method handle from Java source code. From the viewpoint of source code, these methods can take any arguments and their result can be cast to any return type. Formally this is accomplished by giving the invoker methods Object return types and variable arity Object arguments, but they have an additional quality called signature polymorphism which connects this freedom of invocation directly to the JVM execution stack.
As is usual with virtual methods, source-level calls to invokeExact and invoke compile to an invokevirtual instruction. More unusually, the compiler must record the actual argument types, and may not perform method invocation conversions on the arguments. Instead, it must push them on the stack according to their own unconverted types. The method handle object itself is pushed on the stack before the arguments. The compiler then calls the method handle with a symbolic type descriptor which describes the argument and return types.
To issue a complete symbolic type descriptor, the compiler must also determine the return type. This is based on a cast on the method invocation expression, if there is one, or else Object if the invocation is an expression or else void if the invocation is a statement. The cast may be to a primitive type (but not void).
As a corner case, an uncasted null argument is given a symbolic type descriptor of java.lang.Void. The ambiguity with the type Void is harmless, since there are no references of type Void except the null reference.
Method handle invocation The first time a invokevirtual instruction is executed it is linked, by symbolically resolving the names in the instruction and verifying that the method call is statically legal. This is true of calls to invokeExact and invoke. In this case, the symbolic type descriptor emitted by the compiler is checked for correct syntax and names it contains are resolved. Thus, an invokevirtual instruction which invokes a method handle will always link, as long as the symbolic type descriptor is syntactically well-formed and the types exist.
When the invokevirtual is executed after linking, the receiving method handle's type is first checked by the JVM to ensure that it matches the symbolic type descriptor. If the type match fails, it means that the method which the caller is invoking is not present on the individual method handle being invoked.
In the case of invokeExact, the type descriptor of the invocation (after resolving symbolic type names) must exactly match the method type of the receiving method handle. In the case of plain, inexact invoke, the resolved type descriptor must be a valid argument to the receiver's asType method. Thus, plain invoke is more permissive than invokeExact.
After type matching, a call to invokeExact directly and immediately invoke the method handle's underlying method (or other behavior, as the case may be).
A call to plain invoke works the same as a call to invokeExact, if the symbolic type descriptor specified by the caller exactly matches the method handle's own type. If there is a type mismatch, invoke attempts to adjust the type of the receiving method handle, as if by a call to asType, to obtain an exactly invokable method handle M2. This allows a more powerful negotiation of method type between caller and callee.
(Note: The adjusted method handle M2 is not directly observable, and implementations are therefore not required to materialize it.)
Invocation checking In typical programs, method handle type matching will usually succeed. But if a match fails, the JVM will throw a WrongMethodTypeException, either directly (in the case of invokeExact) or indirectly as if by a failed call to asType (in the case of invoke).
Thus, a method type mismatch which might show up as a linkage error in a statically typed program can show up as a dynamic WrongMethodTypeException in a program which uses method handles.
Because method types contain "live" Class objects, method type matching takes into account both types names and class loaders. Thus, even if a method handle M is created in one class loader L1 and used in another L2, method handle calls are type-safe, because the caller's symbolic type descriptor, as resolved in L2, is matched against the original callee method's symbolic type descriptor, as resolved in L1. The resolution in L1 happens when M is created and its type is assigned, while the resolution in L2 happens when the invokevirtual instruction is linked.
Apart from the checking of type descriptors, a method handle's capability to call its underlying method is unrestricted. If a method handle is formed on a non-public method by a class that has access to that method, the resulting handle can be used in any place by any caller who receives a reference to it.
Unlike with the Core Reflection API, where access is checked every time a reflective method is invoked, method handle access checking is performed when the method handle is created. In the case of ldc (see below), access checking is performed as part of linking the constant pool entry underlying the constant method handle.
Thus, handles to non-public methods, or to methods in non-public classes, should generally be kept secret. They should not be passed to untrusted code unless their use from the untrusted code would be harmless.
Method handle creation Java code can create a method handle that directly accesses any method, constructor, or field that is accessible to that code. This is done via a reflective, capability-based API called MethodHandles.Lookup For example, a static method handle can be obtained from Lookup.findStatic. There are also conversion methods from Core Reflection API objects, such as Lookup.unreflect.
Like classes and strings, method handles that correspond to accessible fields, methods, and constructors can also be represented directly in a class file's constant pool as constants to be loaded by ldc bytecodes. A new type of constant pool entry, CONSTANT_MethodHandle, refers directly to an associated CONSTANT_Methodref, CONSTANT_InterfaceMethodref, or CONSTANT_Fieldref constant pool entry. (For full details on method handle constants, see sections 4.4.8 and 5.4.3.5 of the Java Virtual Machine Specification.)
Method handles produced by lookups or constant loads from methods or constructors with the variable arity modifier bit (0x0080) have a corresponding variable arity, as if they were defined with the help of asVarargsCollector.
A method reference may refer either to a static or non-static method. In the non-static case, the method handle type includes an explicit receiver argument, prepended before any other arguments. In the method handle's type, the initial receiver argument is typed according to the class under which the method was initially requested. (E.g., if a non-static method handle is obtained via ldc, the type of the receiver is the class named in the constant pool entry.)
Method handle constants are subject to the same link-time access checks their corresponding bytecode instructions, and the ldc instruction will throw corresponding linkage errors if the bytecode behaviors would throw such errors.
As a corollary of this, access to protected members is restricted to receivers only of the accessing class, or one of its subclasses, and the accessing class must in turn be a subclass (or package sibling) of the protected member's defining class. If a method reference refers to a protected non-static method or field of a class outside the current package, the receiver argument will be narrowed to the type of the accessing class.
When a method handle to a virtual method is invoked, the method is always looked up in the receiver (that is, the first argument).
A non-virtual method handle to a specific virtual method implementation can also be created. These do not perform virtual lookup based on receiver type. Such a method handle simulates the effect of an invokespecial instruction to the same method.
Usage examples Here are some examples of usage:
Object x, y; String s; int i; MethodType mt; MethodHandle mh; MethodHandles.Lookup lookup = MethodHandles.lookup(); // mt is (char,char)String mt = MethodType.methodType(String.class, char.class, char.class); mh = lookup.findVirtual(String.class, "replace", mt); s = (String) mh.invokeExact("daddy",'d','n'); // invokeExact(Ljava/lang/String;CC)Ljava/lang/String; assertEquals(s, "nanny"); // weakly typed invocation (using MHs.invoke) s = (String) mh.invokeWithArguments("sappy", 'p', 'v'); assertEquals(s, "savvy"); // mt is (Object[])List mt = MethodType.methodType(java.util.List.class, Object[].class); mh = lookup.findStatic(java.util.Arrays.class, "asList", mt); assert(mh.isVarargsCollector()); x = mh.invoke("one", "two"); // invoke(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object; assertEquals(x, java.util.Arrays.asList("one","two")); // mt is (Object,Object,Object)Object mt = MethodType.genericMethodType(3); mh = mh.asType(mt); x = mh.invokeExact((Object)1, (Object)2, (Object)3); // invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; assertEquals(x, java.util.Arrays.asList(1,2,3)); // mt is ()int mt = MethodType.methodType(int.class); mh = lookup.findVirtual(java.util.List.class, "size", mt); i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3)); // invokeExact(Ljava/util/List;)I assert(i == 3); mt = MethodType.methodType(void.class, String.class); mh = lookup.findVirtual(java.io.PrintStream.class, "println", mt); mh.invokeExact(System.out, "Hello, world."); // invokeExact(Ljava/io/PrintStream;Ljava/lang/String;)V Each of the above calls to invokeExact or plain invoke generates a single invokevirtual instruction with the symbolic type descriptor indicated in the following comment. In these examples, the helper method assertEquals is assumed to be a method which calls Objects.equals on its arguments, and asserts that the result is true.
Exceptions The methods invokeExact and invoke are declared to throw Throwable, which is to say that there is no static restriction on what a method handle can throw. Since the JVM does not distinguish between checked and unchecked exceptions (other than by their class, of course), there is no particular effect on bytecode shape from ascribing checked exceptions to method handle invocations. But in Java source code, methods which perform method handle calls must either explicitly throw Throwable, or else must catch all throwables locally, rethrowing only those which are legal in the context, and wrapping ones which are illegal.
Signature polymorphism The unusual compilation and linkage behavior of invokeExact and plain invoke is referenced by the term signature polymorphism. As defined in the Java Language Specification, a signature polymorphic method is one which can operate with any of a wide range of call signatures and return types.
In source code, a call to a signature polymorphic method will compile, regardless of the requested symbolic type descriptor. As usual, the Java compiler emits an invokevirtual instruction with the given symbolic type descriptor against the named method. The unusual part is that the symbolic type descriptor is derived from the actual argument and return types, not from the method declaration.
When the JVM processes bytecode containing signature polymorphic calls, it will successfully link any such call, regardless of its symbolic type descriptor. (In order to retain type safety, the JVM will guard such calls with suitable dynamic type checks, as described elsewhere.)
Bytecode generators, including the compiler back end, are required to emit untransformed symbolic type descriptors for these methods. Tools which determine symbolic linkage are required to accept such untransformed descriptors, without reporting linkage errors.
Interoperation between method handles and the Core Reflection API Using factory methods in the Lookup API, any class member represented by a Core Reflection API object can be converted to a behaviorally equivalent method handle. For example, a reflective Method can be converted to a method handle using Lookup.unreflect. The resulting method handles generally provide more direct and efficient access to the underlying class members.
As a special case, when the Core Reflection API is used to view the signature polymorphic methods invokeExact or plain invoke in this class, they appear as ordinary non-polymorphic methods. Their reflective appearance, as viewed by Class.getDeclaredMethod, is unaffected by their special status in this API. For example, Method.getModifiers will report exactly those modifier bits required for any similarly declared method, including in this case native and varargs bits.
As with any reflected method, these methods (when reflected) may be invoked via java.lang.reflect.Method.invoke. However, such reflective calls do not result in method handle invocations. Such a call, if passed the required argument (a single one, of type Object[]), will ignore the argument and will throw an UnsupportedOperationException.
Since invokevirtual instructions can natively invoke method handles under any symbolic type descriptor, this reflective view conflicts with the normal presentation of these methods via bytecodes. Thus, these two native methods, when reflectively viewed by Class.getDeclaredMethod, may be regarded as placeholders only.
In order to obtain an invoker method for a particular type descriptor, use MethodHandles.exactInvoker, or MethodHandles.invoker. The Lookup.findVirtual API is also able to return a method handle to call invokeExact or plain invoke, for any specified type descriptor .
Interoperation between method handles and Java generics A method handle can be obtained on a method, constructor, or field which is declared with Java generic types. As with the Core Reflection API, the type of the method handle will constructed from the erasure of the source-level type. When a method handle is invoked, the types of its arguments or the return value cast type may be generic types or type instances. If this occurs, the compiler will replace those types by their erasures when it constructs the symbolic type descriptor for the invokevirtual instruction.
Method handles do not represent their function-like types in terms of Java parameterized (generic) types, because there are three mismatches between function-like types and parameterized Java types.
Method types range over all possible arities, from no arguments to up to the maximum number of allowed arguments. Generics are not variadic, and so cannot represent this. Method types can specify arguments of primitive types, which Java generic types cannot range over. Higher order functions over method handles (combinators) are often generic across a wide range of function types, including those of multiple arities. It is impossible to represent such genericity with a Java type parameter.
Arity limits The JVM imposes on all methods and constructors of any kind an absolute limit of 255 stacked arguments. This limit can appear more restrictive in certain cases:
A long or double argument counts (for purposes of arity limits) as two argument slots. A non-static method consumes an extra argument for the object on which the method is called. A constructor consumes an extra argument for the object which is being constructed. Since a method handle’s invoke method (or other signature-polymorphic method) is non-virtual, it consumes an extra argument for the method handle itself, in addition to any non-virtual receiver object.
These limits imply that certain method handles cannot be created, solely because of the JVM limit on stacked arguments. For example, if a static JVM method accepts exactly 255 arguments, a method handle cannot be created for it. Attempts to create method handles with impossible method types lead to an IllegalArgumentException. In particular, a method handle’s type must not have an arity of the exact maximum 255.
A method handle is a typed, directly executable reference to an underlying method, constructor, field, or similar low-level operation, with optional transformations of arguments or return values. These transformations are quite general, and include such patterns as conversion, insertion, deletion, and substitution. Method handle contents Method handles are dynamically and strongly typed according to their parameter and return types. They are not distinguished by the name or the defining class of their underlying methods. A method handle must be invoked using a symbolic type descriptor which matches the method handle's own type descriptor. Every method handle reports its type descriptor via the type accessor. This type descriptor is a MethodType object, whose structure is a series of classes, one of which is the return type of the method (or void.class if none). A method handle's type controls the types of invocations it accepts, and the kinds of transformations that apply to it. A method handle contains a pair of special invoker methods called invokeExact and invoke. Both invoker methods provide direct access to the method handle's underlying method, constructor, field, or other operation, as modified by transformations of arguments and return values. Both invokers accept calls which exactly match the method handle's own type. The plain, inexact invoker also accepts a range of other call types. Method handles are immutable and have no visible state. Of course, they can be bound to underlying methods or data which exhibit state. With respect to the Java Memory Model, any method handle will behave as if all of its (internal) fields are final variables. This means that any method handle made visible to the application will always be fully formed. This is true even if the method handle is published through a shared variable in a data race. Method handles cannot be subclassed by the user. Implementations may (or may not) create internal subclasses of MethodHandle which may be visible via the Object.getClass operation. The programmer should not draw conclusions about a method handle from its specific class, as the method handle class hierarchy (if any) may change from time to time or across implementations from different vendors. Method handle compilation A Java method call expression naming invokeExact or invoke can invoke a method handle from Java source code. From the viewpoint of source code, these methods can take any arguments and their result can be cast to any return type. Formally this is accomplished by giving the invoker methods Object return types and variable arity Object arguments, but they have an additional quality called signature polymorphism which connects this freedom of invocation directly to the JVM execution stack. As is usual with virtual methods, source-level calls to invokeExact and invoke compile to an invokevirtual instruction. More unusually, the compiler must record the actual argument types, and may not perform method invocation conversions on the arguments. Instead, it must push them on the stack according to their own unconverted types. The method handle object itself is pushed on the stack before the arguments. The compiler then calls the method handle with a symbolic type descriptor which describes the argument and return types. To issue a complete symbolic type descriptor, the compiler must also determine the return type. This is based on a cast on the method invocation expression, if there is one, or else Object if the invocation is an expression or else void if the invocation is a statement. The cast may be to a primitive type (but not void). As a corner case, an uncasted null argument is given a symbolic type descriptor of java.lang.Void. The ambiguity with the type Void is harmless, since there are no references of type Void except the null reference. Method handle invocation The first time a invokevirtual instruction is executed it is linked, by symbolically resolving the names in the instruction and verifying that the method call is statically legal. This is true of calls to invokeExact and invoke. In this case, the symbolic type descriptor emitted by the compiler is checked for correct syntax and names it contains are resolved. Thus, an invokevirtual instruction which invokes a method handle will always link, as long as the symbolic type descriptor is syntactically well-formed and the types exist. When the invokevirtual is executed after linking, the receiving method handle's type is first checked by the JVM to ensure that it matches the symbolic type descriptor. If the type match fails, it means that the method which the caller is invoking is not present on the individual method handle being invoked. In the case of invokeExact, the type descriptor of the invocation (after resolving symbolic type names) must exactly match the method type of the receiving method handle. In the case of plain, inexact invoke, the resolved type descriptor must be a valid argument to the receiver's asType method. Thus, plain invoke is more permissive than invokeExact. After type matching, a call to invokeExact directly and immediately invoke the method handle's underlying method (or other behavior, as the case may be). A call to plain invoke works the same as a call to invokeExact, if the symbolic type descriptor specified by the caller exactly matches the method handle's own type. If there is a type mismatch, invoke attempts to adjust the type of the receiving method handle, as if by a call to asType, to obtain an exactly invokable method handle M2. This allows a more powerful negotiation of method type between caller and callee. (Note: The adjusted method handle M2 is not directly observable, and implementations are therefore not required to materialize it.) Invocation checking In typical programs, method handle type matching will usually succeed. But if a match fails, the JVM will throw a WrongMethodTypeException, either directly (in the case of invokeExact) or indirectly as if by a failed call to asType (in the case of invoke). Thus, a method type mismatch which might show up as a linkage error in a statically typed program can show up as a dynamic WrongMethodTypeException in a program which uses method handles. Because method types contain "live" Class objects, method type matching takes into account both types names and class loaders. Thus, even if a method handle M is created in one class loader L1 and used in another L2, method handle calls are type-safe, because the caller's symbolic type descriptor, as resolved in L2, is matched against the original callee method's symbolic type descriptor, as resolved in L1. The resolution in L1 happens when M is created and its type is assigned, while the resolution in L2 happens when the invokevirtual instruction is linked. Apart from the checking of type descriptors, a method handle's capability to call its underlying method is unrestricted. If a method handle is formed on a non-public method by a class that has access to that method, the resulting handle can be used in any place by any caller who receives a reference to it. Unlike with the Core Reflection API, where access is checked every time a reflective method is invoked, method handle access checking is performed when the method handle is created. In the case of ldc (see below), access checking is performed as part of linking the constant pool entry underlying the constant method handle. Thus, handles to non-public methods, or to methods in non-public classes, should generally be kept secret. They should not be passed to untrusted code unless their use from the untrusted code would be harmless. Method handle creation Java code can create a method handle that directly accesses any method, constructor, or field that is accessible to that code. This is done via a reflective, capability-based API called MethodHandles.Lookup For example, a static method handle can be obtained from Lookup.findStatic. There are also conversion methods from Core Reflection API objects, such as Lookup.unreflect. Like classes and strings, method handles that correspond to accessible fields, methods, and constructors can also be represented directly in a class file's constant pool as constants to be loaded by ldc bytecodes. A new type of constant pool entry, CONSTANT_MethodHandle, refers directly to an associated CONSTANT_Methodref, CONSTANT_InterfaceMethodref, or CONSTANT_Fieldref constant pool entry. (For full details on method handle constants, see sections 4.4.8 and 5.4.3.5 of the Java Virtual Machine Specification.) Method handles produced by lookups or constant loads from methods or constructors with the variable arity modifier bit (0x0080) have a corresponding variable arity, as if they were defined with the help of asVarargsCollector. A method reference may refer either to a static or non-static method. In the non-static case, the method handle type includes an explicit receiver argument, prepended before any other arguments. In the method handle's type, the initial receiver argument is typed according to the class under which the method was initially requested. (E.g., if a non-static method handle is obtained via ldc, the type of the receiver is the class named in the constant pool entry.) Method handle constants are subject to the same link-time access checks their corresponding bytecode instructions, and the ldc instruction will throw corresponding linkage errors if the bytecode behaviors would throw such errors. As a corollary of this, access to protected members is restricted to receivers only of the accessing class, or one of its subclasses, and the accessing class must in turn be a subclass (or package sibling) of the protected member's defining class. If a method reference refers to a protected non-static method or field of a class outside the current package, the receiver argument will be narrowed to the type of the accessing class. When a method handle to a virtual method is invoked, the method is always looked up in the receiver (that is, the first argument). A non-virtual method handle to a specific virtual method implementation can also be created. These do not perform virtual lookup based on receiver type. Such a method handle simulates the effect of an invokespecial instruction to the same method. Usage examples Here are some examples of usage: Object x, y; String s; int i; MethodType mt; MethodHandle mh; MethodHandles.Lookup lookup = MethodHandles.lookup(); // mt is (char,char)String mt = MethodType.methodType(String.class, char.class, char.class); mh = lookup.findVirtual(String.class, "replace", mt); s = (String) mh.invokeExact("daddy",'d','n'); // invokeExact(Ljava/lang/String;CC)Ljava/lang/String; assertEquals(s, "nanny"); // weakly typed invocation (using MHs.invoke) s = (String) mh.invokeWithArguments("sappy", 'p', 'v'); assertEquals(s, "savvy"); // mt is (Object[])List mt = MethodType.methodType(java.util.List.class, Object[].class); mh = lookup.findStatic(java.util.Arrays.class, "asList", mt); assert(mh.isVarargsCollector()); x = mh.invoke("one", "two"); // invoke(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object; assertEquals(x, java.util.Arrays.asList("one","two")); // mt is (Object,Object,Object)Object mt = MethodType.genericMethodType(3); mh = mh.asType(mt); x = mh.invokeExact((Object)1, (Object)2, (Object)3); // invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; assertEquals(x, java.util.Arrays.asList(1,2,3)); // mt is ()int mt = MethodType.methodType(int.class); mh = lookup.findVirtual(java.util.List.class, "size", mt); i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3)); // invokeExact(Ljava/util/List;)I assert(i == 3); mt = MethodType.methodType(void.class, String.class); mh = lookup.findVirtual(java.io.PrintStream.class, "println", mt); mh.invokeExact(System.out, "Hello, world."); // invokeExact(Ljava/io/PrintStream;Ljava/lang/String;)V Each of the above calls to invokeExact or plain invoke generates a single invokevirtual instruction with the symbolic type descriptor indicated in the following comment. In these examples, the helper method assertEquals is assumed to be a method which calls Objects.equals on its arguments, and asserts that the result is true. Exceptions The methods invokeExact and invoke are declared to throw Throwable, which is to say that there is no static restriction on what a method handle can throw. Since the JVM does not distinguish between checked and unchecked exceptions (other than by their class, of course), there is no particular effect on bytecode shape from ascribing checked exceptions to method handle invocations. But in Java source code, methods which perform method handle calls must either explicitly throw Throwable, or else must catch all throwables locally, rethrowing only those which are legal in the context, and wrapping ones which are illegal. Signature polymorphism The unusual compilation and linkage behavior of invokeExact and plain invoke is referenced by the term signature polymorphism. As defined in the Java Language Specification, a signature polymorphic method is one which can operate with any of a wide range of call signatures and return types. In source code, a call to a signature polymorphic method will compile, regardless of the requested symbolic type descriptor. As usual, the Java compiler emits an invokevirtual instruction with the given symbolic type descriptor against the named method. The unusual part is that the symbolic type descriptor is derived from the actual argument and return types, not from the method declaration. When the JVM processes bytecode containing signature polymorphic calls, it will successfully link any such call, regardless of its symbolic type descriptor. (In order to retain type safety, the JVM will guard such calls with suitable dynamic type checks, as described elsewhere.) Bytecode generators, including the compiler back end, are required to emit untransformed symbolic type descriptors for these methods. Tools which determine symbolic linkage are required to accept such untransformed descriptors, without reporting linkage errors. Interoperation between method handles and the Core Reflection API Using factory methods in the Lookup API, any class member represented by a Core Reflection API object can be converted to a behaviorally equivalent method handle. For example, a reflective Method can be converted to a method handle using Lookup.unreflect. The resulting method handles generally provide more direct and efficient access to the underlying class members. As a special case, when the Core Reflection API is used to view the signature polymorphic methods invokeExact or plain invoke in this class, they appear as ordinary non-polymorphic methods. Their reflective appearance, as viewed by Class.getDeclaredMethod, is unaffected by their special status in this API. For example, Method.getModifiers will report exactly those modifier bits required for any similarly declared method, including in this case native and varargs bits. As with any reflected method, these methods (when reflected) may be invoked via java.lang.reflect.Method.invoke. However, such reflective calls do not result in method handle invocations. Such a call, if passed the required argument (a single one, of type Object[]), will ignore the argument and will throw an UnsupportedOperationException. Since invokevirtual instructions can natively invoke method handles under any symbolic type descriptor, this reflective view conflicts with the normal presentation of these methods via bytecodes. Thus, these two native methods, when reflectively viewed by Class.getDeclaredMethod, may be regarded as placeholders only. In order to obtain an invoker method for a particular type descriptor, use MethodHandles.exactInvoker, or MethodHandles.invoker. The Lookup.findVirtual API is also able to return a method handle to call invokeExact or plain invoke, for any specified type descriptor . Interoperation between method handles and Java generics A method handle can be obtained on a method, constructor, or field which is declared with Java generic types. As with the Core Reflection API, the type of the method handle will constructed from the erasure of the source-level type. When a method handle is invoked, the types of its arguments or the return value cast type may be generic types or type instances. If this occurs, the compiler will replace those types by their erasures when it constructs the symbolic type descriptor for the invokevirtual instruction. Method handles do not represent their function-like types in terms of Java parameterized (generic) types, because there are three mismatches between function-like types and parameterized Java types. Method types range over all possible arities, from no arguments to up to the maximum number of allowed arguments. Generics are not variadic, and so cannot represent this. Method types can specify arguments of primitive types, which Java generic types cannot range over. Higher order functions over method handles (combinators) are often generic across a wide range of function types, including those of multiple arities. It is impossible to represent such genericity with a Java type parameter. Arity limits The JVM imposes on all methods and constructors of any kind an absolute limit of 255 stacked arguments. This limit can appear more restrictive in certain cases: A long or double argument counts (for purposes of arity limits) as two argument slots. A non-static method consumes an extra argument for the object on which the method is called. A constructor consumes an extra argument for the object which is being constructed. Since a method handle’s invoke method (or other signature-polymorphic method) is non-virtual, it consumes an extra argument for the method handle itself, in addition to any non-virtual receiver object. These limits imply that certain method handles cannot be created, solely because of the JVM limit on stacked arguments. For example, if a static JVM method accepts exactly 255 arguments, a method handle cannot be created for it. Attempts to create method handles with impossible method types lead to an IllegalArgumentException. In particular, a method handle’s type must not have an arity of the exact maximum 255.
A symbolic reference obtained by cracking a direct method handle into its consitutent symbolic parts. To crack a direct method handle, call Lookup.revealDirect. Direct Method Handles A direct method handle represents a method, constructor, or field without any intervening argument bindings or other transformations. The method, constructor, or field referred to by a direct method handle is called its underlying member. Direct method handles may be obtained in any of these ways:
By executing an ldc instruction on a CONSTANT_MethodHandle constant. (See the Java Virtual Machine Specification, sections 4.4.8 and 5.4.3.) By calling one of the Lookup Factory Methods, such as Lookup.findVirtual, to resolve a symbolic reference into a method handle. A symbolic reference consists of a class, name string, and type. By calling the factory method Lookup.unreflect or Lookup.unreflectSpecial to convert a Method into a method handle. By calling the factory method Lookup.unreflectConstructor to convert a Constructor into a method handle. By calling the factory method Lookup.unreflectGetter or Lookup.unreflectSetter to convert a Field into a method handle.
Restrictions on Cracking Given a suitable Lookup object, it is possible to crack any direct method handle to recover a symbolic reference for the underlying method, constructor, or field. Cracking must be done via a Lookup object equivalent to that which created the target method handle, or which has enough access permissions to recreate an equivalent method handle.
If the underlying method is caller sensitive, the direct method handle will have been "bound" to a particular caller class, the lookup class of the lookup object used to create it. Cracking this method handle with a different lookup class will fail even if the underlying method is public (like Class.forName).
The requirement of lookup object matching provides a "fast fail" behavior for programs which may otherwise trust erroneous revelation of a method handle with symbolic information (or caller binding) from an unexpected scope. Use MethodHandles.reflectAs(java.lang.Class<T>, java.lang.invoke.MethodHandle) to override this limitation.
Reference kinds The Lookup Factory Methods correspond to all major use cases for methods, constructors, and fields. These use cases may be distinguished using small integers as follows:
reference kinddescriptive namescopememberbehavior
1REF_getFieldclass
FT f;(T) this.f;
2REF_getStaticclass or interface
staticFT f;(T) C.f;
3REF_putFieldclass
FT f;this.f = x;
4REF_putStaticclass
staticFT f;C.f = arg;
5REF_invokeVirtualclass
T m(A*);(T) this.m(arg*);
6REF_invokeStaticclass or interface
staticT m(A*);(T) C.m(arg*);
7REF_invokeSpecialclass or interface
T m(A*);(T) super.m(arg*);
8REF_newInvokeSpecialclass
C(A*);new C(arg*);
9REF_invokeInterfaceinterface
T m(A*);(T) this.m(arg*);
A symbolic reference obtained by cracking a direct method handle into its consitutent symbolic parts. To crack a direct method handle, call Lookup.revealDirect. Direct Method Handles A direct method handle represents a method, constructor, or field without any intervening argument bindings or other transformations. The method, constructor, or field referred to by a direct method handle is called its underlying member. Direct method handles may be obtained in any of these ways: By executing an ldc instruction on a CONSTANT_MethodHandle constant. (See the Java Virtual Machine Specification, sections 4.4.8 and 5.4.3.) By calling one of the Lookup Factory Methods, such as Lookup.findVirtual, to resolve a symbolic reference into a method handle. A symbolic reference consists of a class, name string, and type. By calling the factory method Lookup.unreflect or Lookup.unreflectSpecial to convert a Method into a method handle. By calling the factory method Lookup.unreflectConstructor to convert a Constructor into a method handle. By calling the factory method Lookup.unreflectGetter or Lookup.unreflectSetter to convert a Field into a method handle. Restrictions on Cracking Given a suitable Lookup object, it is possible to crack any direct method handle to recover a symbolic reference for the underlying method, constructor, or field. Cracking must be done via a Lookup object equivalent to that which created the target method handle, or which has enough access permissions to recreate an equivalent method handle. If the underlying method is caller sensitive, the direct method handle will have been "bound" to a particular caller class, the lookup class of the lookup object used to create it. Cracking this method handle with a different lookup class will fail even if the underlying method is public (like Class.forName). The requirement of lookup object matching provides a "fast fail" behavior for programs which may otherwise trust erroneous revelation of a method handle with symbolic information (or caller binding) from an unexpected scope. Use MethodHandles.reflectAs(java.lang.Class<T>, java.lang.invoke.MethodHandle) to override this limitation. Reference kinds The Lookup Factory Methods correspond to all major use cases for methods, constructors, and fields. These use cases may be distinguished using small integers as follows: reference kinddescriptive namescopememberbehavior 1REF_getFieldclass FT f;(T) this.f; 2REF_getStaticclass or interface staticFT f;(T) C.f; 3REF_putFieldclass FT f;this.f = x; 4REF_putStaticclass staticFT f;C.f = arg; 5REF_invokeVirtualclass T m(A*);(T) this.m(arg*); 6REF_invokeStaticclass or interface staticT m(A*);(T) C.m(arg*); 7REF_invokeSpecialclass or interface T m(A*);(T) super.m(arg*); 8REF_newInvokeSpecialclass C(A*);new C(arg*); 9REF_invokeInterfaceinterface T m(A*);(T) this.m(arg*);
This class consists exclusively of static methods that help adapt method handles to other JVM types, such as interfaces.
This class consists exclusively of static methods that help adapt method handles to other JVM types, such as interfaces.
This class consists exclusively of static methods that operate on or return method handles. They fall into several categories:
Lookup methods which help create method handles for methods and fields. Combinator methods, which combine or transform pre-existing method handles into new ones. Other factory methods to create method handles that emulate other common JVM operations or control flow patterns.
This class consists exclusively of static methods that operate on or return method handles. They fall into several categories: Lookup methods which help create method handles for methods and fields. Combinator methods, which combine or transform pre-existing method handles into new ones. Other factory methods to create method handles that emulate other common JVM operations or control flow patterns.
A lookup object is a factory for creating method handles, when the creation requires access checking. Method handles do not perform access checks when they are called, but rather when they are created. Therefore, method handle access restrictions must be enforced when a method handle is created. The caller class against which those restrictions are enforced is known as the lookup class.
A lookup class which needs to create method handles will call MethodHandles.lookup to create a factory for itself. When the Lookup factory object is created, the identity of the lookup class is determined, and securely stored in the Lookup object. The lookup class (or its delegates) may then use factory methods on the Lookup object to create method handles for access-checked members. This includes all methods, constructors, and fields which are allowed to the lookup class, even private ones.
Lookup Factory Methods The factory methods on a Lookup object correspond to all major use cases for methods, constructors, and fields. Each method handle created by a factory method is the functional equivalent of a particular bytecode behavior. (Bytecode behaviors are described in section 5.4.3.5 of the Java Virtual Machine Specification.) Here is a summary of the correspondence between these factory methods and the behavior the resulting method handles:
lookup expression
member
bytecode behavior
lookup.findGetter(C.class,"f",FT.class)
FT f;(T) this.f;
lookup.findStaticGetter(C.class,"f",FT.class)
staticFT f;(T) C.f;
lookup.findSetter(C.class,"f",FT.class)
FT f;this.f = x;
lookup.findStaticSetter(C.class,"f",FT.class)
staticFT f;C.f = arg;
lookup.findVirtual(C.class,"m",MT)
T m(A*);(T) this.m(arg*);
lookup.findStatic(C.class,"m",MT)
staticT m(A*);(T) C.m(arg*);
lookup.findSpecial(C.class,"m",MT,this.class)
T m(A*);(T) super.m(arg*);
lookup.findConstructor(C.class,MT)
C(A*);new C(arg*);
lookup.unreflectGetter(aField)
(static)?FT f;(FT) aField.get(thisOrNull);
lookup.unreflectSetter(aField)
(static)?FT f;aField.set(thisOrNull, arg);
lookup.unreflect(aMethod)
(static)?T m(A*);(T) aMethod.invoke(thisOrNull, arg*);
lookup.unreflectConstructor(aConstructor)
C(A*);(C) aConstructor.newInstance(arg*);
lookup.unreflect(aMethod)
(static)?T m(A*);(T) aMethod.invoke(thisOrNull, arg*);
Here, the type C is the class or interface being searched for a member, documented as a parameter named refc in the lookup methods. The method type MT is composed from the return type T and the sequence of argument types A*. The constructor also has a sequence of argument types A* and is deemed to return the newly-created object of type C. Both MT and the field type FT are documented as a parameter named type. The formal parameter this stands for the self-reference of type C; if it is present, it is always the leading argument to the method handle invocation. (In the case of some protected members, this may be restricted in type to the lookup class; see below.) The name arg stands for all the other method handle arguments. In the code examples for the Core Reflection API, the name thisOrNull stands for a null reference if the accessed method or field is static, and this otherwise. The names aMethod, aField, and aConstructor stand for reflective objects corresponding to the given members.
In cases where the given member is of variable arity (i.e., a method or constructor) the returned method handle will also be of variable arity. In all other cases, the returned method handle will be of fixed arity.
Discussion: The equivalence between looked-up method handles and underlying class members and bytecode behaviors can break down in a few ways:
If C is not symbolically accessible from the lookup class's loader, the lookup can still succeed, even when there is no equivalent Java expression or bytecoded constant. Likewise, if T or MT is not symbolically accessible from the lookup class's loader, the lookup can still succeed. For example, lookups for MethodHandle.invokeExact and MethodHandle.invoke will always succeed, regardless of requested type. If there is a security manager installed, it can forbid the lookup on various grounds (see below). By contrast, the ldc instruction on a CONSTANT_MethodHandle constant is not subject to security manager checks. If the looked-up method has a very large arity, the method handle creation may fail, due to the method handle type having too many parameters.
Access checking Access checks are applied in the factory methods of Lookup, when a method handle is created. This is a key difference from the Core Reflection API, since java.lang.reflect.Method.invoke performs access checking against every caller, on every call.
All access checks start from a Lookup object, which compares its recorded lookup class against all requests to create method handles. A single Lookup object can be used to create any number of access-checked method handles, all checked against a single lookup class.
A Lookup object can be shared with other trusted code, such as a metaobject protocol. A shared Lookup object delegates the capability to create method handles on private members of the lookup class. Even if privileged code uses the Lookup object, the access checking is confined to the privileges of the original lookup class.
A lookup can fail, because the containing class is not accessible to the lookup class, or because the desired class member is missing, or because the desired class member is not accessible to the lookup class, or because the lookup object is not trusted enough to access the member. In any of these cases, a ReflectiveOperationException will be thrown from the attempted lookup. The exact class will be one of the following:
NoSuchMethodException — if a method is requested but does not exist NoSuchFieldException — if a field is requested but does not exist IllegalAccessException — if the member exists but an access check fails
In general, the conditions under which a method handle may be looked up for a method M are no more restrictive than the conditions under which the lookup class could have compiled, verified, and resolved a call to M. Where the JVM would raise exceptions like NoSuchMethodError, a method handle lookup will generally raise a corresponding checked exception, such as NoSuchMethodException. And the effect of invoking the method handle resulting from the lookup is exactly equivalent to executing the compiled, verified, and resolved call to M. The same point is true of fields and constructors.
Discussion: Access checks only apply to named and reflected methods, constructors, and fields. Other method handle creation methods, such as MethodHandle.asType, do not require any access checks, and are used independently of any Lookup object.
If the desired member is protected, the usual JVM rules apply, including the requirement that the lookup class must be either be in the same package as the desired member, or must inherit that member. (See the Java Virtual Machine Specification, sections 4.9.2, 5.4.3.5, and 6.4.) In addition, if the desired member is a non-static field or method in a different package, the resulting method handle may only be applied to objects of the lookup class or one of its subclasses. This requirement is enforced by narrowing the type of the leading this parameter from C (which will necessarily be a superclass of the lookup class) to the lookup class itself.
The JVM imposes a similar requirement on invokespecial instruction, that the receiver argument must match both the resolved method and the current class. Again, this requirement is enforced by narrowing the type of the leading parameter to the resulting method handle. (See the Java Virtual Machine Specification, section 4.10.1.9.)
The JVM represents constructors and static initializer blocks as internal methods with special names ("<init>" and "<clinit>"). The internal syntax of invocation instructions allows them to refer to such internal methods as if they were normal methods, but the JVM bytecode verifier rejects them. A lookup of such an internal method will produce a NoSuchMethodException.
In some cases, access between nested classes is obtained by the Java compiler by creating an wrapper method to access a private method of another class in the same top-level declaration. For example, a nested class C.D can access private members within other related classes such as C, C.D.E, or C.B, but the Java compiler may need to generate wrapper methods in those related classes. In such cases, a Lookup object on C.E would be unable to those private members. A workaround for this limitation is the Lookup.in method, which can transform a lookup on C.E into one on any of those other classes, without special elevation of privilege.
The accesses permitted to a given lookup object may be limited, according to its set of lookupModes, to a subset of members normally accessible to the lookup class. For example, the publicLookup method produces a lookup object which is only allowed to access public members in public classes. The caller sensitive method lookup produces a lookup object with full capabilities relative to its caller class, to emulate all supported bytecode behaviors. Also, the Lookup.in method may produce a lookup object with fewer access modes than the original lookup object.
Discussion of private access: We say that a lookup has private access if its lookup modes include the possibility of accessing private members. As documented in the relevant methods elsewhere, only lookups with private access possess the following capabilities:
access private fields, methods, and constructors of the lookup class create method handles which invoke caller sensitive methods, such as Class.forName create method handles which emulate invokespecial instructions avoid package access checks for classes accessible to the lookup class create delegated lookup objects which have private access to other classes within the same package member
Each of these permissions is a consequence of the fact that a lookup object with private access can be securely traced back to an originating class, whose bytecode behaviors and Java language access permissions can be reliably determined and emulated by method handles.
Security manager interactions Although bytecode instructions can only refer to classes in a related class loader, this API can search for methods in any class, as long as a reference to its Class object is available. Such cross-loader references are also possible with the Core Reflection API, and are impossible to bytecode instructions such as invokestatic or getfield. There is a java.lang.security manager API to allow applications to check such cross-loader references. These checks apply to both the MethodHandles.Lookup API and the Core Reflection API (as found on Class).
If a security manager is present, member lookups are subject to additional checks. From one to three calls are made to the security manager. Any of these calls can refuse access by throwing a SecurityException. Define smgr as the security manager, lookc as the lookup class of the current lookup object, refc as the containing class in which the member is being sought, and defc as the class in which the member is actually defined. The value lookc is defined as not present if the current lookup object does not have private access. The calls are made according to the following rules:
Step 1: If lookc is not present, or if its class loader is not the same as or an ancestor of the class loader of refc, then smgr.checkPackageAccess(refcPkg) is called, where refcPkg is the package of refc. Step 2: If the retrieved member is not public and lookc is not present, then smgr.checkPermission with RuntimePermission("accessDeclaredMembers") is called. Step 3: If the retrieved member is not public, and if lookc is not present, and if defc and refc are different, then smgr.checkPackageAccess(defcPkg) is called, where defcPkg is the package of defc.
Security checks are performed after other access checks have passed. Therefore, the above rules presuppose a member that is public, or else that is being accessed from a lookup class that has rights to access the member.
Caller sensitive methods A small number of Java methods have a special property called caller sensitivity. A caller-sensitive method can behave differently depending on the identity of its immediate caller.
If a method handle for a caller-sensitive method is requested, the general rules for bytecode behaviors apply, but they take account of the lookup class in a special way. The resulting method handle behaves as if it were called from an instruction contained in the lookup class, so that the caller-sensitive method detects the lookup class. (By contrast, the invoker of the method handle is disregarded.) Thus, in the case of caller-sensitive methods, different lookup classes may give rise to differently behaving method handles.
In cases where the lookup object is publicLookup(), or some other lookup object without private access, the lookup class is disregarded. In such cases, no caller-sensitive method handle can be created, access is forbidden, and the lookup fails with an IllegalAccessException.
Discussion: For example, the caller-sensitive method Class.forName(x) can return varying classes or throw varying exceptions, depending on the class loader of the class that calls it. A public lookup of Class.forName will fail, because there is no reasonable way to determine its bytecode behavior.
If an application caches method handles for broad sharing, it should use publicLookup() to create them. If there is a lookup of Class.forName, it will fail, and the application must take appropriate action in that case. It may be that a later lookup, perhaps during the invocation of a bootstrap method, can incorporate the specific identity of the caller, making the method accessible.
The function MethodHandles.lookup is caller sensitive so that there can be a secure foundation for lookups. Nearly all other methods in the JSR 292 API rely on lookup objects to check access requests.
A lookup object is a factory for creating method handles, when the creation requires access checking. Method handles do not perform access checks when they are called, but rather when they are created. Therefore, method handle access restrictions must be enforced when a method handle is created. The caller class against which those restrictions are enforced is known as the lookup class. A lookup class which needs to create method handles will call MethodHandles.lookup to create a factory for itself. When the Lookup factory object is created, the identity of the lookup class is determined, and securely stored in the Lookup object. The lookup class (or its delegates) may then use factory methods on the Lookup object to create method handles for access-checked members. This includes all methods, constructors, and fields which are allowed to the lookup class, even private ones. Lookup Factory Methods The factory methods on a Lookup object correspond to all major use cases for methods, constructors, and fields. Each method handle created by a factory method is the functional equivalent of a particular bytecode behavior. (Bytecode behaviors are described in section 5.4.3.5 of the Java Virtual Machine Specification.) Here is a summary of the correspondence between these factory methods and the behavior the resulting method handles: lookup expression member bytecode behavior lookup.findGetter(C.class,"f",FT.class) FT f;(T) this.f; lookup.findStaticGetter(C.class,"f",FT.class) staticFT f;(T) C.f; lookup.findSetter(C.class,"f",FT.class) FT f;this.f = x; lookup.findStaticSetter(C.class,"f",FT.class) staticFT f;C.f = arg; lookup.findVirtual(C.class,"m",MT) T m(A*);(T) this.m(arg*); lookup.findStatic(C.class,"m",MT) staticT m(A*);(T) C.m(arg*); lookup.findSpecial(C.class,"m",MT,this.class) T m(A*);(T) super.m(arg*); lookup.findConstructor(C.class,MT) C(A*);new C(arg*); lookup.unreflectGetter(aField) (static)?FT f;(FT) aField.get(thisOrNull); lookup.unreflectSetter(aField) (static)?FT f;aField.set(thisOrNull, arg); lookup.unreflect(aMethod) (static)?T m(A*);(T) aMethod.invoke(thisOrNull, arg*); lookup.unreflectConstructor(aConstructor) C(A*);(C) aConstructor.newInstance(arg*); lookup.unreflect(aMethod) (static)?T m(A*);(T) aMethod.invoke(thisOrNull, arg*); Here, the type C is the class or interface being searched for a member, documented as a parameter named refc in the lookup methods. The method type MT is composed from the return type T and the sequence of argument types A*. The constructor also has a sequence of argument types A* and is deemed to return the newly-created object of type C. Both MT and the field type FT are documented as a parameter named type. The formal parameter this stands for the self-reference of type C; if it is present, it is always the leading argument to the method handle invocation. (In the case of some protected members, this may be restricted in type to the lookup class; see below.) The name arg stands for all the other method handle arguments. In the code examples for the Core Reflection API, the name thisOrNull stands for a null reference if the accessed method or field is static, and this otherwise. The names aMethod, aField, and aConstructor stand for reflective objects corresponding to the given members. In cases where the given member is of variable arity (i.e., a method or constructor) the returned method handle will also be of variable arity. In all other cases, the returned method handle will be of fixed arity. Discussion: The equivalence between looked-up method handles and underlying class members and bytecode behaviors can break down in a few ways: If C is not symbolically accessible from the lookup class's loader, the lookup can still succeed, even when there is no equivalent Java expression or bytecoded constant. Likewise, if T or MT is not symbolically accessible from the lookup class's loader, the lookup can still succeed. For example, lookups for MethodHandle.invokeExact and MethodHandle.invoke will always succeed, regardless of requested type. If there is a security manager installed, it can forbid the lookup on various grounds (see below). By contrast, the ldc instruction on a CONSTANT_MethodHandle constant is not subject to security manager checks. If the looked-up method has a very large arity, the method handle creation may fail, due to the method handle type having too many parameters. Access checking Access checks are applied in the factory methods of Lookup, when a method handle is created. This is a key difference from the Core Reflection API, since java.lang.reflect.Method.invoke performs access checking against every caller, on every call. All access checks start from a Lookup object, which compares its recorded lookup class against all requests to create method handles. A single Lookup object can be used to create any number of access-checked method handles, all checked against a single lookup class. A Lookup object can be shared with other trusted code, such as a metaobject protocol. A shared Lookup object delegates the capability to create method handles on private members of the lookup class. Even if privileged code uses the Lookup object, the access checking is confined to the privileges of the original lookup class. A lookup can fail, because the containing class is not accessible to the lookup class, or because the desired class member is missing, or because the desired class member is not accessible to the lookup class, or because the lookup object is not trusted enough to access the member. In any of these cases, a ReflectiveOperationException will be thrown from the attempted lookup. The exact class will be one of the following: NoSuchMethodException — if a method is requested but does not exist NoSuchFieldException — if a field is requested but does not exist IllegalAccessException — if the member exists but an access check fails In general, the conditions under which a method handle may be looked up for a method M are no more restrictive than the conditions under which the lookup class could have compiled, verified, and resolved a call to M. Where the JVM would raise exceptions like NoSuchMethodError, a method handle lookup will generally raise a corresponding checked exception, such as NoSuchMethodException. And the effect of invoking the method handle resulting from the lookup is exactly equivalent to executing the compiled, verified, and resolved call to M. The same point is true of fields and constructors. Discussion: Access checks only apply to named and reflected methods, constructors, and fields. Other method handle creation methods, such as MethodHandle.asType, do not require any access checks, and are used independently of any Lookup object. If the desired member is protected, the usual JVM rules apply, including the requirement that the lookup class must be either be in the same package as the desired member, or must inherit that member. (See the Java Virtual Machine Specification, sections 4.9.2, 5.4.3.5, and 6.4.) In addition, if the desired member is a non-static field or method in a different package, the resulting method handle may only be applied to objects of the lookup class or one of its subclasses. This requirement is enforced by narrowing the type of the leading this parameter from C (which will necessarily be a superclass of the lookup class) to the lookup class itself. The JVM imposes a similar requirement on invokespecial instruction, that the receiver argument must match both the resolved method and the current class. Again, this requirement is enforced by narrowing the type of the leading parameter to the resulting method handle. (See the Java Virtual Machine Specification, section 4.10.1.9.) The JVM represents constructors and static initializer blocks as internal methods with special names ("<init>" and "<clinit>"). The internal syntax of invocation instructions allows them to refer to such internal methods as if they were normal methods, but the JVM bytecode verifier rejects them. A lookup of such an internal method will produce a NoSuchMethodException. In some cases, access between nested classes is obtained by the Java compiler by creating an wrapper method to access a private method of another class in the same top-level declaration. For example, a nested class C.D can access private members within other related classes such as C, C.D.E, or C.B, but the Java compiler may need to generate wrapper methods in those related classes. In such cases, a Lookup object on C.E would be unable to those private members. A workaround for this limitation is the Lookup.in method, which can transform a lookup on C.E into one on any of those other classes, without special elevation of privilege. The accesses permitted to a given lookup object may be limited, according to its set of lookupModes, to a subset of members normally accessible to the lookup class. For example, the publicLookup method produces a lookup object which is only allowed to access public members in public classes. The caller sensitive method lookup produces a lookup object with full capabilities relative to its caller class, to emulate all supported bytecode behaviors. Also, the Lookup.in method may produce a lookup object with fewer access modes than the original lookup object. Discussion of private access: We say that a lookup has private access if its lookup modes include the possibility of accessing private members. As documented in the relevant methods elsewhere, only lookups with private access possess the following capabilities: access private fields, methods, and constructors of the lookup class create method handles which invoke caller sensitive methods, such as Class.forName create method handles which emulate invokespecial instructions avoid package access checks for classes accessible to the lookup class create delegated lookup objects which have private access to other classes within the same package member Each of these permissions is a consequence of the fact that a lookup object with private access can be securely traced back to an originating class, whose bytecode behaviors and Java language access permissions can be reliably determined and emulated by method handles. Security manager interactions Although bytecode instructions can only refer to classes in a related class loader, this API can search for methods in any class, as long as a reference to its Class object is available. Such cross-loader references are also possible with the Core Reflection API, and are impossible to bytecode instructions such as invokestatic or getfield. There is a java.lang.security manager API to allow applications to check such cross-loader references. These checks apply to both the MethodHandles.Lookup API and the Core Reflection API (as found on Class). If a security manager is present, member lookups are subject to additional checks. From one to three calls are made to the security manager. Any of these calls can refuse access by throwing a SecurityException. Define smgr as the security manager, lookc as the lookup class of the current lookup object, refc as the containing class in which the member is being sought, and defc as the class in which the member is actually defined. The value lookc is defined as not present if the current lookup object does not have private access. The calls are made according to the following rules: Step 1: If lookc is not present, or if its class loader is not the same as or an ancestor of the class loader of refc, then smgr.checkPackageAccess(refcPkg) is called, where refcPkg is the package of refc. Step 2: If the retrieved member is not public and lookc is not present, then smgr.checkPermission with RuntimePermission("accessDeclaredMembers") is called. Step 3: If the retrieved member is not public, and if lookc is not present, and if defc and refc are different, then smgr.checkPackageAccess(defcPkg) is called, where defcPkg is the package of defc. Security checks are performed after other access checks have passed. Therefore, the above rules presuppose a member that is public, or else that is being accessed from a lookup class that has rights to access the member. Caller sensitive methods A small number of Java methods have a special property called caller sensitivity. A caller-sensitive method can behave differently depending on the identity of its immediate caller. If a method handle for a caller-sensitive method is requested, the general rules for bytecode behaviors apply, but they take account of the lookup class in a special way. The resulting method handle behaves as if it were called from an instruction contained in the lookup class, so that the caller-sensitive method detects the lookup class. (By contrast, the invoker of the method handle is disregarded.) Thus, in the case of caller-sensitive methods, different lookup classes may give rise to differently behaving method handles. In cases where the lookup object is publicLookup(), or some other lookup object without private access, the lookup class is disregarded. In such cases, no caller-sensitive method handle can be created, access is forbidden, and the lookup fails with an IllegalAccessException. Discussion: For example, the caller-sensitive method Class.forName(x) can return varying classes or throw varying exceptions, depending on the class loader of the class that calls it. A public lookup of Class.forName will fail, because there is no reasonable way to determine its bytecode behavior. If an application caches method handles for broad sharing, it should use publicLookup() to create them. If there is a lookup of Class.forName, it will fail, and the application must take appropriate action in that case. It may be that a later lookup, perhaps during the invocation of a bootstrap method, can incorporate the specific identity of the caller, making the method accessible. The function MethodHandles.lookup is caller sensitive so that there can be a secure foundation for lookups. Nearly all other methods in the JSR 292 API rely on lookup objects to check access requests.
A method type represents the arguments and return type accepted and returned by a method handle, or the arguments and return type passed and expected by a method handle caller. Method types must be properly matched between a method handle and all its callers, and the JVM's operations enforce this matching at, specifically during calls to MethodHandle.invokeExact and MethodHandle.invoke, and during execution of invokedynamic instructions.
The structure is a return type accompanied by any number of parameter types. The types (primitive, void, and reference) are represented by Class objects. (For ease of exposition, we treat void as if it were a type. In fact, it denotes the absence of a return type.)
All instances of MethodType are immutable. Two instances are completely interchangeable if they compare equal. Equality depends on pairwise correspondence of the return and parameter types and on nothing else.
This type can be created only by factory methods. All factory methods may cache values, though caching is not guaranteed. Some factory methods are static, while others are virtual methods which modify precursor method types, e.g., by changing a selected parameter.
Factory methods which operate on groups of parameter types are systematically presented in two versions, so that both Java arrays and Java lists can be used to work with groups of parameter types. The query methods parameterArray and parameterList also provide a choice between arrays and lists.
MethodType objects are sometimes derived from bytecode instructions such as invokedynamic, specifically from the type descriptor strings associated with the instructions in a class file's constant pool.
Like classes and strings, method types can also be represented directly in a class file's constant pool as constants. A method type may be loaded by an ldc instruction which refers to a suitable CONSTANT_MethodType constant pool entry. The entry refers to a CONSTANT_Utf8 spelling for the descriptor string. (For full details on method type constants, see sections 4.4.8 and 5.4.3.5 of the Java Virtual Machine Specification.)
When the JVM materializes a MethodType from a descriptor string, all classes named in the descriptor must be accessible, and will be loaded. (But the classes need not be initialized, as is the case with a CONSTANT_Class.) This loading may occur at any time before the MethodType object is first derived.
A method type represents the arguments and return type accepted and returned by a method handle, or the arguments and return type passed and expected by a method handle caller. Method types must be properly matched between a method handle and all its callers, and the JVM's operations enforce this matching at, specifically during calls to MethodHandle.invokeExact and MethodHandle.invoke, and during execution of invokedynamic instructions. The structure is a return type accompanied by any number of parameter types. The types (primitive, void, and reference) are represented by Class objects. (For ease of exposition, we treat void as if it were a type. In fact, it denotes the absence of a return type.) All instances of MethodType are immutable. Two instances are completely interchangeable if they compare equal. Equality depends on pairwise correspondence of the return and parameter types and on nothing else. This type can be created only by factory methods. All factory methods may cache values, though caching is not guaranteed. Some factory methods are static, while others are virtual methods which modify precursor method types, e.g., by changing a selected parameter. Factory methods which operate on groups of parameter types are systematically presented in two versions, so that both Java arrays and Java lists can be used to work with groups of parameter types. The query methods parameterArray and parameterList also provide a choice between arrays and lists. MethodType objects are sometimes derived from bytecode instructions such as invokedynamic, specifically from the type descriptor strings associated with the instructions in a class file's constant pool. Like classes and strings, method types can also be represented directly in a class file's constant pool as constants. A method type may be loaded by an ldc instruction which refers to a suitable CONSTANT_MethodType constant pool entry. The entry refers to a CONSTANT_Utf8 spelling for the descriptor string. (For full details on method type constants, see sections 4.4.8 and 5.4.3.5 of the Java Virtual Machine Specification.) When the JVM materializes a MethodType from a descriptor string, all classes named in the descriptor must be accessible, and will be loaded. (But the classes need not be initialized, as is the case with a CONSTANT_Class.) This loading may occur at any time before the MethodType object is first derived.
A MutableCallSite is a CallSite whose target variable behaves like an ordinary field. An invokedynamic instruction linked to a MutableCallSite delegates all calls to the site's current target. The dynamic invoker of a mutable call site also delegates each call to the site's current target.
Here is an example of a mutable call site which introduces a state variable into a method handle chain. JavaDocExamplesTest.testMutableCallSite
MutableCallSite name = new MutableCallSite(MethodType.methodType(String.class)); MethodHandle MH_name = name.dynamicInvoker(); MethodType MT_str1 = MethodType.methodType(String.class); MethodHandle MH_upcase = MethodHandles.lookup() .findVirtual(String.class, "toUpperCase", MT_str1); MethodHandle worker1 = MethodHandles.filterReturnValue(MH_name, MH_upcase); name.setTarget(MethodHandles.constant(String.class, "Rocky")); assertEquals("ROCKY", (String) worker1.invokeExact()); name.setTarget(MethodHandles.constant(String.class, "Fred")); assertEquals("FRED", (String) worker1.invokeExact()); // (mutation can be continued indefinitely)
The same call site may be used in several places at once.
MethodType MT_str2 = MethodType.methodType(String.class, String.class); MethodHandle MH_cat = lookup().findVirtual(String.class, "concat", methodType(String.class, String.class)); MethodHandle MH_dear = MethodHandles.insertArguments(MH_cat, 1, ", dear?"); MethodHandle worker2 = MethodHandles.filterReturnValue(MH_name, MH_dear); assertEquals("Fred, dear?", (String) worker2.invokeExact()); name.setTarget(MethodHandles.constant(String.class, "Wilma")); assertEquals("WILMA", (String) worker1.invokeExact()); assertEquals("Wilma, dear?", (String) worker2.invokeExact());
Non-synchronization of target values: A write to a mutable call site's target does not force other threads to become aware of the updated value. Threads which do not perform suitable synchronization actions relative to the updated call site may cache the old target value and delay their use of the new target value indefinitely. (This is a normal consequence of the Java Memory Model as applied to object fields.)
The syncAll operation provides a way to force threads to accept a new target value, even if there is no other synchronization.
For target values which will be frequently updated, consider using a java.lang.invoke.volatile call site instead.
A MutableCallSite is a CallSite whose target variable behaves like an ordinary field. An invokedynamic instruction linked to a MutableCallSite delegates all calls to the site's current target. The dynamic invoker of a mutable call site also delegates each call to the site's current target. Here is an example of a mutable call site which introduces a state variable into a method handle chain. JavaDocExamplesTest.testMutableCallSite MutableCallSite name = new MutableCallSite(MethodType.methodType(String.class)); MethodHandle MH_name = name.dynamicInvoker(); MethodType MT_str1 = MethodType.methodType(String.class); MethodHandle MH_upcase = MethodHandles.lookup() .findVirtual(String.class, "toUpperCase", MT_str1); MethodHandle worker1 = MethodHandles.filterReturnValue(MH_name, MH_upcase); name.setTarget(MethodHandles.constant(String.class, "Rocky")); assertEquals("ROCKY", (String) worker1.invokeExact()); name.setTarget(MethodHandles.constant(String.class, "Fred")); assertEquals("FRED", (String) worker1.invokeExact()); // (mutation can be continued indefinitely) The same call site may be used in several places at once. MethodType MT_str2 = MethodType.methodType(String.class, String.class); MethodHandle MH_cat = lookup().findVirtual(String.class, "concat", methodType(String.class, String.class)); MethodHandle MH_dear = MethodHandles.insertArguments(MH_cat, 1, ", dear?"); MethodHandle worker2 = MethodHandles.filterReturnValue(MH_name, MH_dear); assertEquals("Fred, dear?", (String) worker2.invokeExact()); name.setTarget(MethodHandles.constant(String.class, "Wilma")); assertEquals("WILMA", (String) worker1.invokeExact()); assertEquals("Wilma, dear?", (String) worker2.invokeExact()); Non-synchronization of target values: A write to a mutable call site's target does not force other threads to become aware of the updated value. Threads which do not perform suitable synchronization actions relative to the updated call site may cache the old target value and delay their use of the new target value indefinitely. (This is a normal consequence of the Java Memory Model as applied to object fields.) The syncAll operation provides a way to force threads to accept a new target value, even if there is no other synchronization. For target values which will be frequently updated, consider using a java.lang.invoke.volatile call site instead.
Serialized form of a lambda expression. The properties of this class represent the information that is present at the lambda factory site, including static metafactory arguments such as the identity of the primary functional interface method and the identity of the implementation method, as well as dynamic metafactory arguments such as values captured from the lexical scope at the time of lambda capture.
Implementors of serializable lambdas, such as compilers or language runtime libraries, are expected to ensure that instances deserialize properly. One means to do so is to ensure that the writeReplace method returns an instance of SerializedLambda, rather than allowing default serialization to proceed.
SerializedLambda has a readResolve method that looks for a (possibly private) static method called $deserializeLambda$(SerializedLambda) in the capturing class, invokes that with itself as the first argument, and returns the result. Lambda classes implementing $deserializeLambda$ are responsible for validating that the properties of the SerializedLambda are consistent with a lambda actually captured by that class.
Serialized form of a lambda expression. The properties of this class represent the information that is present at the lambda factory site, including static metafactory arguments such as the identity of the primary functional interface method and the identity of the implementation method, as well as dynamic metafactory arguments such as values captured from the lexical scope at the time of lambda capture. Implementors of serializable lambdas, such as compilers or language runtime libraries, are expected to ensure that instances deserialize properly. One means to do so is to ensure that the writeReplace method returns an instance of SerializedLambda, rather than allowing default serialization to proceed. SerializedLambda has a readResolve method that looks for a (possibly private) static method called $deserializeLambda$(SerializedLambda) in the capturing class, invokes that with itself as the first argument, and returns the result. Lambda classes implementing $deserializeLambda$ are responsible for validating that the properties of the SerializedLambda are consistent with a lambda actually captured by that class.
A SwitchPoint is an object which can publish state transitions to other threads. A switch point is initially in the valid state, but may at any time be changed to the invalid state. Invalidation cannot be reversed. A switch point can combine a guarded pair of method handles into a guarded delegator. The guarded delegator is a method handle which delegates to one of the old method handles. The state of the switch point determines which of the two gets the delegation.
A single switch point may be used to control any number of method handles. (Indirectly, therefore, it can control any number of call sites.) This is done by using the single switch point as a factory for combining any number of guarded method handle pairs into guarded delegators.
When a guarded delegator is created from a guarded pair, the pair is wrapped in a new method handle M, which is permanently associated with the switch point that created it. Each pair consists of a target T and a fallback F. While the switch point is valid, invocations to M are delegated to T. After it is invalidated, invocations are delegated to F.
Invalidation is global and immediate, as if the switch point contained a volatile boolean variable consulted on every call to M. The invalidation is also permanent, which means the switch point can change state only once. The switch point will always delegate to F after being invalidated. At that point guardWithTest may ignore T and return F.
Here is an example of a switch point in action:
MethodHandle MH_strcat = MethodHandles.lookup() .findVirtual(String.class, "concat", MethodType.methodType(String.class, String.class)); SwitchPoint spt = new SwitchPoint(); assert(!spt.hasBeenInvalidated()); // the following steps may be repeated to re-use the same switch point: MethodHandle worker1 = MH_strcat; MethodHandle worker2 = MethodHandles.permuteArguments(MH_strcat, MH_strcat.type(), 1, 0); MethodHandle worker = spt.guardWithTest(worker1, worker2); assertEquals("method", (String) worker.invokeExact("met", "hod")); SwitchPoint.invalidateAll(new SwitchPoint[]{ spt }); assert(spt.hasBeenInvalidated()); assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
Discussion: Switch points are useful without subclassing. They may also be subclassed. This may be useful in order to associate application-specific invalidation logic with the switch point. Notice that there is no permanent association between a switch point and the method handles it produces and consumes. The garbage collector may collect method handles produced or consumed by a switch point independently of the lifetime of the switch point itself.
Implementation Note: A switch point behaves as if implemented on top of MutableCallSite, approximately as follows:
public class SwitchPoint { private static final MethodHandle K_true = MethodHandles.constant(boolean.class, true), K_false = MethodHandles.constant(boolean.class, false); private final MutableCallSite mcs; private final MethodHandle mcsInvoker; public SwitchPoint() { this.mcs = new MutableCallSite(K_true); this.mcsInvoker = mcs.dynamicInvoker(); } public MethodHandle guardWithTest( MethodHandle target, MethodHandle fallback) { // Note: mcsInvoker is of type ()boolean. // Target and fallback may take any arguments, but must have the same type. return MethodHandles.guardWithTest(this.mcsInvoker, target, fallback); } public static void invalidateAll(SwitchPoint[] spts) { List<MutableCallSite> mcss = new ArrayList<>(); for (SwitchPoint spt : spts) mcss.add(spt.mcs); for (MutableCallSite mcs : mcss) mcs.setTarget(K_false); MutableCallSite.syncAll(mcss.toArray(new MutableCallSite[0])); } }
A SwitchPoint is an object which can publish state transitions to other threads. A switch point is initially in the valid state, but may at any time be changed to the invalid state. Invalidation cannot be reversed. A switch point can combine a guarded pair of method handles into a guarded delegator. The guarded delegator is a method handle which delegates to one of the old method handles. The state of the switch point determines which of the two gets the delegation. A single switch point may be used to control any number of method handles. (Indirectly, therefore, it can control any number of call sites.) This is done by using the single switch point as a factory for combining any number of guarded method handle pairs into guarded delegators. When a guarded delegator is created from a guarded pair, the pair is wrapped in a new method handle M, which is permanently associated with the switch point that created it. Each pair consists of a target T and a fallback F. While the switch point is valid, invocations to M are delegated to T. After it is invalidated, invocations are delegated to F. Invalidation is global and immediate, as if the switch point contained a volatile boolean variable consulted on every call to M. The invalidation is also permanent, which means the switch point can change state only once. The switch point will always delegate to F after being invalidated. At that point guardWithTest may ignore T and return F. Here is an example of a switch point in action: MethodHandle MH_strcat = MethodHandles.lookup() .findVirtual(String.class, "concat", MethodType.methodType(String.class, String.class)); SwitchPoint spt = new SwitchPoint(); assert(!spt.hasBeenInvalidated()); // the following steps may be repeated to re-use the same switch point: MethodHandle worker1 = MH_strcat; MethodHandle worker2 = MethodHandles.permuteArguments(MH_strcat, MH_strcat.type(), 1, 0); MethodHandle worker = spt.guardWithTest(worker1, worker2); assertEquals("method", (String) worker.invokeExact("met", "hod")); SwitchPoint.invalidateAll(new SwitchPoint[]{ spt }); assert(spt.hasBeenInvalidated()); assertEquals("hodmet", (String) worker.invokeExact("met", "hod")); Discussion: Switch points are useful without subclassing. They may also be subclassed. This may be useful in order to associate application-specific invalidation logic with the switch point. Notice that there is no permanent association between a switch point and the method handles it produces and consumes. The garbage collector may collect method handles produced or consumed by a switch point independently of the lifetime of the switch point itself. Implementation Note: A switch point behaves as if implemented on top of MutableCallSite, approximately as follows: public class SwitchPoint { private static final MethodHandle K_true = MethodHandles.constant(boolean.class, true), K_false = MethodHandles.constant(boolean.class, false); private final MutableCallSite mcs; private final MethodHandle mcsInvoker; public SwitchPoint() { this.mcs = new MutableCallSite(K_true); this.mcsInvoker = mcs.dynamicInvoker(); } public MethodHandle guardWithTest( MethodHandle target, MethodHandle fallback) { // Note: mcsInvoker is of type ()boolean. // Target and fallback may take any arguments, but must have the same type. return MethodHandles.guardWithTest(this.mcsInvoker, target, fallback); } public static void invalidateAll(SwitchPoint[] spts) { List<MutableCallSite> mcss = new ArrayList<>(); for (SwitchPoint spt : spts) mcss.add(spt.mcs); for (MutableCallSite mcs : mcss) mcs.setTarget(K_false); MutableCallSite.syncAll(mcss.toArray(new MutableCallSite[0])); } }
A VolatileCallSite is a CallSite whose target acts like a volatile variable. An invokedynamic instruction linked to a VolatileCallSite sees updates to its call site target immediately, even if the update occurs in another thread. There may be a performance penalty for such tight coupling between threads.
Unlike MutableCallSite, there is no syncAll operation on volatile call sites, since every write to a volatile variable is implicitly synchronized with reader threads.
In other respects, a VolatileCallSite is interchangeable with MutableCallSite.
A VolatileCallSite is a CallSite whose target acts like a volatile variable. An invokedynamic instruction linked to a VolatileCallSite sees updates to its call site target immediately, even if the update occurs in another thread. There may be a performance penalty for such tight coupling between threads. Unlike MutableCallSite, there is no syncAll operation on volatile call sites, since every write to a volatile variable is implicitly synchronized with reader threads. In other respects, a VolatileCallSite is interchangeable with MutableCallSite.
Thrown to indicate that code has attempted to call a method handle via the wrong method type. As with the bytecode representation of normal Java method calls, method handle calls are strongly typed to a specific type descriptor associated with a call site.
This exception may also be thrown when two method handles are composed, and the system detects that their types cannot be matched up correctly. This amounts to an early evaluation of the type mismatch, at method handle construction time, instead of when the mismatched method handle is called.
Thrown to indicate that code has attempted to call a method handle via the wrong method type. As with the bytecode representation of normal Java method calls, method handle calls are strongly typed to a specific type descriptor associated with a call site. This exception may also be thrown when two method handles are composed, and the system detects that their types cannot be matched up correctly. This amounts to an early evaluation of the type mismatch, at method handle construction time, instead of when the mismatched method handle is called.
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close