Home » openjdk-7 » java.lang.invoke » [javadoc | source]
java.lang.invoke
public static final class: MethodHandles.Lookup [javadoc | source]
java.lang.Object
   java.lang.invoke.MethodHandles$Lookup
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 {@linkplain #lookupClass lookup class}.

A lookup class which needs to create method handles will call MethodHandles.lookup to create a factory for itself. When the {@code Lookup} factory object is created, the identity of the lookup class is determined, and securely stored in the {@code Lookup} object. The lookup class (or its delegates) may then use factory methods on the {@code 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.

The factory methods on a {@code Lookup} object correspond to all major use cases for methods, constructors, and fields. Here is a summary of the correspondence between these factory methods and the behavior the resulting method handles:
lookup expressionmemberbehavior
{@linkplain java.lang.invoke.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)} FT f;(T) this.f;
{@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)} static
FT f;
(T) C.f;
{@linkplain java.lang.invoke.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)} FT f;this.f = x;
{@linkplain java.lang.invoke.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)} static
FT f;
C.f = arg;
{@linkplain java.lang.invoke.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)} T m(A*);(T) this.m(arg*);
{@linkplain java.lang.invoke.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)} static
T m(A*);
(T) C.m(arg*);
{@linkplain java.lang.invoke.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)} T m(A*);(T) super.m(arg*);
{@linkplain java.lang.invoke.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)} C(A*);(T) new C(arg*);
{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)} (static)?
FT f;
(FT) aField.get(thisOrNull);
{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)} (static)?
FT f;
aField.set(thisOrNull, arg);
{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)} (static)?
T m(A*);
(T) aMethod.invoke(thisOrNull, arg*);
{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)} C(A*);(C) aConstructor.newInstance(arg*);
{@linkplain java.lang.invoke.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)} (static)?
T m(A*);
(T) aMethod.invoke(thisOrNull, arg*);
Here, the type {@code C} is the class or interface being searched for a member, documented as a parameter named {@code refc} in the lookup methods. The method or constructor type {@code MT} is composed from the return type {@code T} and the sequence of argument types {@code A*}. Both {@code MT} and the field type {@code FT} are documented as a parameter named {@code type}. The formal parameter {@code this} stands for the self-reference of type {@code C}; if it is present, it is always the leading argument to the method handle invocation. The name {@code arg} stands for all the other method handle arguments. In the code examples for the Core Reflection API, the name {@code thisOrNull} stands for a null reference if the accessed method or field is static, and {@code this} otherwise. The names {@code aMethod}, {@code aField}, and {@code 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 {@linkplain MethodHandle#asVarargsCollector variable arity}. In all other cases, the returned method handle will be of fixed arity.

The equivalence between looked-up method handles and underlying class members can break down in a few ways:

Access checking

Access checks are applied in the factory methods of {@code 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 {@code Lookup} object, which compares its recorded lookup class against all requests to create method handles. A single {@code Lookup} object can be used to create any number of access-checked method handles, all checked against a single lookup class.

A {@code Lookup} object can be shared with other trusted code, such as a metaobject protocol. A shared {@code Lookup} object delegates the capability to create method handles on private members of the lookup class. Even if privileged code uses the {@code 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. In any of these cases, a {@code ReflectiveOperationException} will be thrown from the attempted lookup. The exact class will be one of the following:

In general, the conditions under which a method handle may be looked up for a method {@code M} are exactly equivalent to the conditions under which the lookup class could have compiled and resolved a call to {@code M}. And the effect of invoking the method handle resulting from the lookup is exactly equivalent to executing the compiled and resolved call to {@code M}. The same point is true of fields and constructors.

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 {@code C.D} can access private members within other related classes such as {@code C}, {@code C.D.E}, or {@code C.B}, but the Java compiler may need to generate wrapper methods in those related classes. In such cases, a {@code Lookup} object on {@code 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 {@code C.E} into one on any of those other classes, without special elevation of privilege.

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 {@code Class} object is available. Such cross-loader references are also possible with the Core Reflection API, and are impossible to bytecode instructions such as {@code invokestatic} or {@code getfield}. There is a {@linkplain java.lang.SecurityManager security manager API} to allow applications to check such cross-loader references. These checks apply to both the {@code MethodHandles.Lookup} API and the Core Reflection API (as found on Class ).

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 done with static methods of MethodHandles , independently of any {@code Lookup} object.

Security manager interactions

If a security manager is present, member lookups are subject to additional checks. From one to four calls are made to the security manager. Any of these calls can refuse access by throwing a SecurityException . Define {@code smgr} as the security manager, {@code refc} as the containing class in which the member is being sought, and {@code defc} as the class in which the member is actually defined. The calls are made according to the following rules:
Field Summary
public static final  int PUBLIC    A single-bit mask representing {@code public} access, which may contribute to the result of lookupModes . The value, {@code 0x01}, happens to be the same as the value of the {@code public} {@linkplain java.lang.reflect.Modifier#PUBLIC modifier bit}. 
public static final  int PRIVATE    A single-bit mask representing {@code private} access, which may contribute to the result of lookupModes . The value, {@code 0x02}, happens to be the same as the value of the {@code private} {@linkplain java.lang.reflect.Modifier#PRIVATE modifier bit}. 
public static final  int PROTECTED    A single-bit mask representing {@code protected} access, which may contribute to the result of lookupModes . The value, {@code 0x04}, happens to be the same as the value of the {@code protected} {@linkplain java.lang.reflect.Modifier#PROTECTED modifier bit}. 
public static final  int PACKAGE    A single-bit mask representing {@code package} access (default access), which may contribute to the result of lookupModes . The value is {@code 0x08}, which does not correspond meaningfully to any particular {@linkplain java.lang.reflect.Modifier modifier bit}. 
static final  Lookup PUBLIC_LOOKUP    Version of lookup which is trusted minimally. It can only be used to create method handles to publicly accessible members. 
static final  Lookup IMPL_LOOKUP    Package-private version of lookup which is trusted. 
Constructor:
 Lookup() 
 Lookup(Class<?> lookupClass) 
Method from java.lang.invoke.MethodHandles$Lookup Summary:
accessFailedMessage,   bind,   checkAccess,   checkMethod,   checkSecurityManager,   checkSpecialCaller,   checkSymbolicClass,   findConstructor,   findGetter,   findSetter,   findSpecial,   findStatic,   findStaticGetter,   findStaticSetter,   findVirtual,   in,   linkMethodHandleConstant,   lookupClass,   lookupModes,   makeAccessor,   resolveOrFail,   resolveOrFail,   resolveOrFail,   restrictProtectedReceiver,   restrictReceiver,   toString,   unreflect,   unreflectConstructor,   unreflectGetter,   unreflectSetter,   unreflectSpecial
Methods from java.lang.Object:
clone,   equals,   finalize,   getClass,   hashCode,   notify,   notifyAll,   toString,   wait,   wait,   wait
Method from java.lang.invoke.MethodHandles$Lookup Detail:
 String accessFailedMessage(Class<?> refc,
    MemberName m) 
 public MethodHandle bind(Object receiver,
    String name,
    MethodType type) throws NoSuchMethodException, IllegalAccessException 
    Produces an early-bound method handle for a non-static method. The receiver must have a supertype {@code defc} in which a method of the given name and type is accessible to the lookup class. The method and all its argument types must be accessible to the lookup class. The type of the method handle will be that of the method, without any insertion of an additional receiver parameter. The given receiver will be bound into the method handle, so that every call to the method handle will invoke the requested method on the given receiver.

    The returned method handle will have {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if the method's variable arity modifier bit ({@code 0x0080}) is set and the trailing array argument is not the only argument. (If the trailing array argument is the only argument, the given receiver value will be bound to it.)

    This is equivalent to the following code:

    import static java.lang.invoke.MethodHandles.*;
    import static java.lang.invoke.MethodType.*;
    ...
    MethodHandle mh0 = lookup(). findVirtual (defc, name, type);
    MethodHandle mh1 = mh0. bindTo (receiver);
    MethodType mt1 = mh1.type();
    if (mh0.isVarargsCollector())
    mh1 = mh1.asVarargsCollector(mt1.parameterType(mt1.parameterCount()-1));
    return mh1;
    
    where {@code defc} is either {@code receiver.getClass()} or a super type of that class, in which the requested method is accessible to the lookup class. (Note that {@code bindTo} does not preserve variable arity.)
  void checkAccess(Class<?> refc,
    MemberName m) throws IllegalAccessException 
  void checkMethod(Class<?> refc,
    MemberName m,
    boolean wantStatic) throws IllegalAccessException 
  void checkSecurityManager(Class<?> refc,
    MemberName m) 
    Perform necessary access checks. This function performs stack walk magic: do not refactor it.
  void checkSpecialCaller(Class<?> specialCaller) throws IllegalAccessException 
  void checkSymbolicClass(Class<?> refc) throws IllegalAccessException 
 public MethodHandle findConstructor(Class<?> refc,
    MethodType type) throws NoSuchMethodException, IllegalAccessException 
    Produces a method handle which creates an object and initializes it, using the constructor of the specified type. The parameter types of the method handle will be those of the constructor, while the return type will be a reference to the constructor's class. The constructor and all its argument types must be accessible to the lookup class. If the constructor's class has not yet been initialized, that is done immediately, before the method handle is returned.

    Note: The requested type must have a return type of {@code void}. This is consistent with the JVM's treatment of constructor type descriptors.

    The returned method handle will have {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if the constructor's variable arity modifier bit ({@code 0x0080}) is set.

 public MethodHandle findGetter(Class<?> refc,
    String name,
    Class<?> type) throws NoSuchFieldException, IllegalAccessException 
    Produces a method handle giving read access to a non-static field. The type of the method handle will have a return type of the field's value type. The method handle's single argument will be the instance containing the field. Access checking is performed immediately on behalf of the lookup class.
 public MethodHandle findSetter(Class<?> refc,
    String name,
    Class<?> type) throws NoSuchFieldException, IllegalAccessException 
    Produces a method handle giving write access to a non-static field. The type of the method handle will have a void return type. The method handle will take two arguments, the instance containing the field, and the value to be stored. The second argument will be of the field's value type. Access checking is performed immediately on behalf of the lookup class.
 public MethodHandle findSpecial(Class<?> refc,
    String name,
    MethodType type,
    Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException 
    Produces an early-bound method handle for a virtual method, as if called from an {@code invokespecial} instruction from {@code caller}. The type of the method handle will be that of the method, with a suitably restricted receiver type (such as {@code caller}) prepended. The method and all its argument types must be accessible to the caller.

    When called, the handle will treat the first argument as a receiver, but will not dispatch on the receiver's type. (This direct invocation action is identical with that performed by an {@code invokespecial} instruction.)

    If the explicitly specified caller class is not identical with the lookup class, or if this lookup object does not have private access privileges, the access fails.

    The returned method handle will have {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if the method's variable arity modifier bit ({@code 0x0080}) is set.

 public MethodHandle findStatic(Class<?> refc,
    String name,
    MethodType type) throws NoSuchMethodException, IllegalAccessException 
    Produces a method handle for a static method. The type of the method handle will be that of the method. (Since static methods do not take receivers, there is no additional receiver argument inserted into the method handle type, as there would be with findVirtual or findSpecial .) The method and all its argument types must be accessible to the lookup class. If the method's class has not yet been initialized, that is done immediately, before the method handle is returned.

    The returned method handle will have {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if the method's variable arity modifier bit ({@code 0x0080}) is set.

 public MethodHandle findStaticGetter(Class<?> refc,
    String name,
    Class<?> type) throws NoSuchFieldException, IllegalAccessException 
    Produces a method handle giving read access to a static field. The type of the method handle will have a return type of the field's value type. The method handle will take no arguments. Access checking is performed immediately on behalf of the lookup class.
 public MethodHandle findStaticSetter(Class<?> refc,
    String name,
    Class<?> type) throws NoSuchFieldException, IllegalAccessException 
    Produces a method handle giving write access to a static field. The type of the method handle will have a void return type. The method handle will take a single argument, of the field's value type, the value to be stored. Access checking is performed immediately on behalf of the lookup class.
 public MethodHandle findVirtual(Class<?> refc,
    String name,
    MethodType type) throws NoSuchMethodException, IllegalAccessException 
    Produces a method handle for a virtual method. The type of the method handle will be that of the method, with the receiver type (usually {@code refc}) prepended. The method and all its argument types must be accessible to the lookup class.

    When called, the handle will treat the first argument as a receiver and dispatch on the receiver's type to determine which method implementation to enter. (The dispatching action is identical with that performed by an {@code invokevirtual} or {@code invokeinterface} instruction.)

    The returned method handle will have {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if the method's variable arity modifier bit ({@code 0x0080}) is set.

    Because of the general equivalence between {@code invokevirtual} instructions and method handles produced by {@code findVirtual}, if the class is {@code MethodHandle} and the name string is {@code invokeExact} or {@code invoke}, the resulting method handle is equivalent to one produced by MethodHandles.exactInvoker or MethodHandles.invoker with the same {@code type} argument.

 public Lookup in(Class<?> requestedLookupClass) 
    Creates a lookup on the specified new lookup class. The resulting object will report the specified class as its own lookupClass .

    However, the resulting {@code Lookup} object is guaranteed to have no more access capabilities than the original. In particular, access capabilities can be lost as follows:

    • If the new lookup class differs from the old one, protected members will not be accessible by virtue of inheritance. (Protected members may continue to be accessible because of package sharing.)
    • If the new lookup class is in a different package than the old one, protected and default (package) members will not be accessible.
    • If the new lookup class is not within the same package member as the old one, private members will not be accessible.
    • If the new lookup class is not accessible to the old lookup class, then no members, not even public members, will be accessible. (In all other cases, public members will continue to be accessible.)
 MethodHandle linkMethodHandleConstant(int refKind,
    Class<?> defc,
    String name,
    Object type) throws ReflectiveOperationException 
    Hook called from the JVM (via MethodHandleNatives) to link MH constants:
 public Class<?> lookupClass() 
    Tells which class is performing the lookup. It is this class against which checks are performed for visibility and access permissions.

    The class implies a maximum level of access permission, but the permissions may be additionally limited by the bitmask lookupModes , which controls whether non-public members can be accessed.

 public int lookupModes() 
    Tells which access-protection classes of members this lookup object can produce. The result is a bit-mask of the bits {@linkplain #PUBLIC PUBLIC (0x01)}, {@linkplain #PRIVATE PRIVATE (0x02)}, {@linkplain #PROTECTED PROTECTED (0x04)}, and {@linkplain #PACKAGE PACKAGE (0x08)}.

    A freshly-created lookup object on the {@linkplain java.lang.invoke.MethodHandles#lookup() caller's class} has all possible bits set, since the caller class can access all its own members. A lookup object on a new lookup class {@linkplain java.lang.invoke.MethodHandles.Lookup#in created from a previous lookup object} may have some mode bits set to zero. The purpose of this is to restrict access via the new lookup object, so that it can access only names which can be reached by the original lookup object, and also by the new lookup class.

 MethodHandle makeAccessor(Class<?> refc,
    MemberName field,
    boolean trusted,
    boolean isSetter,
    int checkStatic) throws IllegalAccessException 
 MemberName resolveOrFail(Class<?> refc,
    String name,
    Class<?> type,
    boolean isStatic) throws NoSuchFieldException, IllegalAccessException 
 MemberName resolveOrFail(Class<?> refc,
    String name,
    MethodType type,
    boolean isStatic) throws NoSuchMethodException, IllegalAccessException 
 MemberName resolveOrFail(Class<?> refc,
    String name,
    MethodType type,
    boolean isStatic,
    boolean searchSupers,
    Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException 
 MethodHandle restrictProtectedReceiver(MemberName method,
    MethodHandle mh) throws IllegalAccessException 
 MethodHandle restrictReceiver(MemberName method,
    MethodHandle mh,
    Class<?> caller) throws IllegalAccessException 
 public String toString() 
    Displays the name of the class from which lookups are to be made. (The name is the one reported by Class.getName .) If there are restrictions on the access permitted to this lookup, this is indicated by adding a suffix to the class name, consisting of a slash and a keyword. The keyword represents the strongest allowed access, and is chosen as follows:
    • If no access is allowed, the suffix is "/noaccess".
    • If only public access is allowed, the suffix is "/public".
    • If only public and package access are allowed, the suffix is "/package".
    • If only public, package, and private access are allowed, the suffix is "/private".
    If none of the above cases apply, it is the case that full access (public, package, private, and protected) is allowed. In this case, no suffix is added. This is true only of an object obtained originally from MethodHandles.lookup . Objects created by Lookup.in always have restricted access, and will display a suffix.

    (It may seem strange that protected access should be stronger than private access. Viewed independently from package access, protected access is the first to be lost, because it requires a direct subclass relationship between caller and callee.)

 public MethodHandle unreflect(Method m) throws IllegalAccessException 
    Makes a direct method handle to m, if the lookup class has permission. If m is non-static, the receiver argument is treated as an initial argument. If m is virtual, overriding is respected on every call. Unlike the Core Reflection API, exceptions are not wrapped. The type of the method handle will be that of the method, with the receiver type prepended (but only if it is non-static). If the method's {@code accessible} flag is not set, access checking is performed immediately on behalf of the lookup class. If m is not public, do not share the resulting handle with untrusted parties.

    The returned method handle will have {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if the method's variable arity modifier bit ({@code 0x0080}) is set.

 public MethodHandle unreflectConstructor(Constructor c) throws IllegalAccessException 
    Produces a method handle for a reflected constructor. The type of the method handle will be that of the constructor, with the return type changed to the declaring class. The method handle will perform a {@code newInstance} operation, creating a new instance of the constructor's class on the arguments passed to the method handle.

    If the constructor's {@code accessible} flag is not set, access checking is performed immediately on behalf of the lookup class.

    The returned method handle will have {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if the constructor's variable arity modifier bit ({@code 0x0080}) is set.

 public MethodHandle unreflectGetter(Field f) throws IllegalAccessException 
    Produces a method handle giving read access to a reflected field. The type of the method handle will have a return type of the field's value type. If the field is static, the method handle will take no arguments. Otherwise, its single argument will be the instance containing the field. If the field's {@code accessible} flag is not set, access checking is performed immediately on behalf of the lookup class.
 public MethodHandle unreflectSetter(Field f) throws IllegalAccessException 
    Produces a method handle giving write access to a reflected field. The type of the method handle will have a void return type. If the field is static, the method handle will take a single argument, of the field's value type, the value to be stored. Otherwise, the two arguments will be the instance containing the field, and the value to be stored. If the field's {@code accessible} flag is not set, access checking is performed immediately on behalf of the lookup class.
 public MethodHandle unreflectSpecial(Method m,
    Class<?> specialCaller) throws IllegalAccessException 
    Produces a method handle for a reflected method. It will bypass checks for overriding methods on the receiver, as if by a {@code invokespecial} instruction from within the {@code specialCaller}. The type of the method handle will be that of the method, with the special caller type prepended (and not the receiver of the method). If the method's {@code accessible} flag is not set, access checking is performed immediately on behalf of the lookup class, as if {@code invokespecial} instruction were being linked.

    The returned method handle will have {@linkplain MethodHandle#asVarargsCollector variable arity} if and only if the method's variable arity modifier bit ({@code 0x0080}) is set.