public static final class MethodHandles.Lookup extends Object
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.
The factory methods on a 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:
Here, the type
lookup expression member behavior
lookup.findGetter(C.class,"f",FT.class)
FT f; (T) this.f;
lookup.findStaticGetter(C.class,"f",FT.class)
static
FT f;(T) C.f;
lookup.findSetter(C.class,"f",FT.class)
FT f; this.f = x;
lookup.findStaticSetter(C.class,"f",FT.class)
static
FT f;C.f = arg;
lookup.findVirtual(C.class,"m",MT)
T m(A*); (T) this.m(arg*);
lookup.findStatic(C.class,"m",MT)
static
T 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*); (T) 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*);
C
is the class or interface being searched for a member,
documented as a parameter named refc
in the lookup methods.
The method or constructor type MT
is composed from the return type T
and the sequence of argument types A*
.
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.
The equivalence between looked-up method handles and underlying class members can break down in a few ways:
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.
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.
ldc
instruction is not subject to
security manager checks.
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.
In any of these cases, a 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 M
are exactly equivalent to the conditions
under which the lookup class could have compiled and resolved a call to M
.
And the effect of invoking the method handle resulting from the lookup
is exactly equivalent to executing the compiled and resolved call to M
.
The same point is true of fields and constructors.
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.
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.
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 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
).
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 Lookup
object.
SecurityException
.
Define smgr
as the security manager,
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 calls are made according to the following rules:
smgr.checkMemberAccess(refc, Member.PUBLIC)
is called.
refc
,
then smgr.checkPackageAccess(refcPkg)
is called,
where refcPkg
is the package of refc
.
smgr.checkMemberAccess(defc, Member.DECLARED)
is called.
(Note that defc
might be the same as refc
.)
The default implementation of this security manager method
inspects the stack to determine the original caller of
the reflective request (such as findStatic
),
and performs additional permission checks if the
class loader of defc
differs from the class
loader of the class from which the reflective request came.
defc
and refc
are in different class loaders,
and if the class loader of the lookup class is not
the same as or an ancestor of the class loader of defc
,
then smgr.checkPackageAccess(defcPkg)
is called,
where defcPkg
is the package of defc
.
Modifier and Type | Field and Description |
---|---|
static int |
PACKAGE
A single-bit mask representing
package access (default access),
which may contribute to the result of lookupModes . |
static int |
PRIVATE
A single-bit mask representing
private access,
which may contribute to the result of lookupModes . |
static int |
PROTECTED
A single-bit mask representing
protected access,
which may contribute to the result of lookupModes . |
static int |
PUBLIC
A single-bit mask representing
public access,
which may contribute to the result of lookupModes . |
Modifier and Type | Method and Description |
---|---|
MethodHandle |
bind(Object receiver,
String name,
MethodType type)
Produces an early-bound method handle for a non-static method.
|
MethodHandle |
findConstructor(Class<?> refc,
MethodType type)
Produces a method handle which creates an object and initializes it, using
the constructor of the specified type.
|
MethodHandle |
findGetter(Class<?> refc,
String name,
Class<?> type)
Produces a method handle giving read access to a non-static field.
|
MethodHandle |
findSetter(Class<?> refc,
String name,
Class<?> type)
Produces a method handle giving write access to a non-static field.
|
MethodHandle |
findSpecial(Class<?> refc,
String name,
MethodType type,
Class<?> specialCaller)
Produces an early-bound method handle for a virtual method,
as if called from an
invokespecial
instruction from caller . |
MethodHandle |
findStatic(Class<?> refc,
String name,
MethodType type)
Produces a method handle for a static method.
|
MethodHandle |
findStaticGetter(Class<?> refc,
String name,
Class<?> type)
Produces a method handle giving read access to a static field.
|
MethodHandle |
findStaticSetter(Class<?> refc,
String name,
Class<?> type)
Produces a method handle giving write access to a static field.
|
MethodHandle |
findVirtual(Class<?> refc,
String name,
MethodType type)
Produces a method handle for a virtual method.
|
MethodHandles.Lookup |
in(Class<?> requestedLookupClass)
Creates a lookup on the specified new lookup class.
|
Class<?> |
lookupClass()
Tells which class is performing the lookup.
|
int |
lookupModes()
Tells which access-protection classes of members this lookup object can produce.
|
String |
toString()
Displays the name of the class from which lookups are to be made.
|
MethodHandle |
unreflect(Method m)
Makes a direct method handle to m, if the lookup class has permission.
|
MethodHandle |
unreflectConstructor(Constructor c)
Produces a method handle for a reflected constructor.
|
MethodHandle |
unreflectGetter(Field f)
Produces a method handle giving read access to a reflected field.
|
MethodHandle |
unreflectSetter(Field f)
Produces a method handle giving write access to a reflected field.
|
MethodHandle |
unreflectSpecial(Method m,
Class<?> specialCaller)
Produces a method handle for a reflected method.
|
public static final int PUBLIC
public
access,
which may contribute to the result of lookupModes
.
The value, 0x01
, happens to be the same as the value of the
public
modifier bit.public static final int PRIVATE
private
access,
which may contribute to the result of lookupModes
.
The value, 0x02
, happens to be the same as the value of the
private
modifier bit.public static final int PROTECTED
protected
access,
which may contribute to the result of lookupModes
.
The value, 0x04
, happens to be the same as the value of the
protected
modifier bit.public static final int PACKAGE
package
access (default access),
which may contribute to the result of lookupModes
.
The value is 0x08
, which does not correspond meaningfully to
any particular modifier bit.public Class<?> lookupClass()
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()
A freshly-created lookup object on the 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 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.
public MethodHandles.Lookup in(Class<?> requestedLookupClass)
lookupClass
.
However, the resulting Lookup
object is guaranteed
to have no more access capabilities than the original.
In particular, access capabilities can be lost as follows:
requestedLookupClass
- the desired lookup class for the new lookup objectNullPointerException
- if the argument is nullpublic String toString()
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:
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.)
toString
in class Object
in(java.lang.Class<?>)
public MethodHandle findStatic(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException
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
variable arity if and only if
the method's variable arity modifier bit (0x0080
) is set.
refc
- the class from which the method is accessedname
- the name of the methodtype
- the type of the methodNoSuchMethodException
- if the method does not existIllegalAccessException
- if access checking fails,
or if the method is not static
,
or if the method's variable arity modifier bit
is set and asVarargsCollector
failsSecurityException
- if a security manager is present and it
refuses accessNullPointerException
- if any argument is nullpublic MethodHandle findVirtual(Class<?> refc, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException
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
invokevirtual
or invokeinterface
instruction.)
The first argument will be of type refc
if the lookup
class has full privileges to access the member. Otherwise
the member must be protected
and the first argument
will be restricted in type to the lookup class.
The returned method handle will have
variable arity if and only if
the method's variable arity modifier bit (0x0080
) is set.
Because of the general equivalence between invokevirtual
instructions and method handles produced by findVirtual
,
if the class is MethodHandle
and the name string is
invokeExact
or invoke
, the resulting
method handle is equivalent to one produced by
MethodHandles.exactInvoker
or
MethodHandles.invoker
with the same type
argument.
refc
- the class or interface from which the method is accessedname
- the name of the methodtype
- the type of the method, with the receiver argument omittedNoSuchMethodException
- if the method does not existIllegalAccessException
- if access checking fails,
or if the method is static
or if the method's variable arity modifier bit
is set and asVarargsCollector
failsSecurityException
- if a security manager is present and it
refuses accessNullPointerException
- if any argument is nullpublic MethodHandle findConstructor(Class<?> refc, MethodType type) throws NoSuchMethodException, IllegalAccessException
Note: The requested type must have a return type of void
.
This is consistent with the JVM's treatment of constructor type descriptors.
The returned method handle will have
variable arity if and only if
the constructor's variable arity modifier bit (0x0080
) is set.
refc
- the class or interface from which the method is accessedtype
- the type of the method, with the receiver argument omitted, and a void return typeNoSuchMethodException
- if the constructor does not existIllegalAccessException
- if access checking fails
or if the method's variable arity modifier bit
is set and asVarargsCollector
failsSecurityException
- if a security manager is present and it
refuses accessNullPointerException
- if any argument is nullpublic MethodHandle findSpecial(Class<?> refc, String name, MethodType type, Class<?> specialCaller) throws NoSuchMethodException, IllegalAccessException
invokespecial
instruction from caller
.
The type of the method handle will be that of the method,
with a suitably restricted receiver type (such as 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
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
variable arity if and only if
the method's variable arity modifier bit (0x0080
) is set.
refc
- the class or interface from which the method is accessedname
- the name of the method (which must not be "<init>")type
- the type of the method, with the receiver argument omittedspecialCaller
- the proposed calling class to perform the invokespecial
NoSuchMethodException
- if the method does not existIllegalAccessException
- if access checking fails
or if the method's variable arity modifier bit
is set and asVarargsCollector
failsSecurityException
- if a security manager is present and it
refuses accessNullPointerException
- if any argument is nullpublic MethodHandle findGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException
refc
- the class or interface from which the method is accessedname
- the field's nametype
- the field's typeNoSuchFieldException
- if the field does not existIllegalAccessException
- if access checking fails, or if the field is static
SecurityException
- if a security manager is present and it
refuses accessNullPointerException
- if any argument is nullpublic MethodHandle findSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException
refc
- the class or interface from which the method is accessedname
- the field's nametype
- the field's typeNoSuchFieldException
- if the field does not existIllegalAccessException
- if access checking fails, or if the field is static
SecurityException
- if a security manager is present and it
refuses accessNullPointerException
- if any argument is nullpublic MethodHandle findStaticGetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException
refc
- the class or interface from which the method is accessedname
- the field's nametype
- the field's typeNoSuchFieldException
- if the field does not existIllegalAccessException
- if access checking fails, or if the field is not static
SecurityException
- if a security manager is present and it
refuses accessNullPointerException
- if any argument is nullpublic MethodHandle findStaticSetter(Class<?> refc, String name, Class<?> type) throws NoSuchFieldException, IllegalAccessException
refc
- the class or interface from which the method is accessedname
- the field's nametype
- the field's typeNoSuchFieldException
- if the field does not existIllegalAccessException
- if access checking fails, or if the field is not static
SecurityException
- if a security manager is present and it
refuses accessNullPointerException
- if any argument is nullpublic MethodHandle bind(Object receiver, String name, MethodType type) throws NoSuchMethodException, IllegalAccessException
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
variable arity if and only if
the method's variable arity modifier bit (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:
whereimport 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;
defc
is either receiver.getClass()
or a super
type of that class, in which the requested method is accessible
to the lookup class.
(Note that bindTo
does not preserve variable arity.)receiver
- the object from which the method is accessedname
- the name of the methodtype
- the type of the method, with the receiver argument omittedNoSuchMethodException
- if the method does not existIllegalAccessException
- if access checking fails
or if the method's variable arity modifier bit
is set and asVarargsCollector
failsSecurityException
- if a security manager is present and it
refuses accessNullPointerException
- if any argument is nullpublic MethodHandle unreflect(Method m) throws IllegalAccessException
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
variable arity if and only if
the method's variable arity modifier bit (0x0080
) is set.
m
- the reflected methodIllegalAccessException
- if access checking fails
or if the method's variable arity modifier bit
is set and asVarargsCollector
failsNullPointerException
- if the argument is nullpublic MethodHandle unreflectSpecial(Method m, Class<?> specialCaller) throws IllegalAccessException
invokespecial
instruction from within the 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 accessible
flag is not set,
access checking is performed immediately on behalf of the lookup class,
as if invokespecial
instruction were being linked.
The returned method handle will have
variable arity if and only if
the method's variable arity modifier bit (0x0080
) is set.
m
- the reflected methodspecialCaller
- the class nominally calling the methodIllegalAccessException
- if access checking fails
or if the method's variable arity modifier bit
is set and asVarargsCollector
failsNullPointerException
- if any argument is nullpublic MethodHandle unreflectConstructor(Constructor c) throws IllegalAccessException
newInstance
operation,
creating a new instance of the constructor's class on the
arguments passed to the method handle.
If the constructor's accessible
flag is not set,
access checking is performed immediately on behalf of the lookup class.
The returned method handle will have
variable arity if and only if
the constructor's variable arity modifier bit (0x0080
) is set.
c
- the reflected constructorIllegalAccessException
- if access checking fails
or if the method's variable arity modifier bit
is set and asVarargsCollector
failsNullPointerException
- if the argument is nullpublic MethodHandle unreflectGetter(Field f) throws IllegalAccessException
accessible
flag is not set,
access checking is performed immediately on behalf of the lookup class.f
- the reflected fieldIllegalAccessException
- if access checking failsNullPointerException
- if the argument is nullpublic MethodHandle unreflectSetter(Field f) throws IllegalAccessException
accessible
flag is not set,
access checking is performed immediately on behalf of the lookup class.f
- the reflected fieldIllegalAccessException
- if access checking failsNullPointerException
- if the argument is null Submit a bug or feature
For further API reference and developer documentation, see Java SE Documentation. That documentation contains more detailed, developer-targeted descriptions, with conceptual overviews, definitions of terms, workarounds, and working code examples.
Copyright © 1993, 2013, Oracle and/or its affiliates. All rights reserved.