Proxy
provides static methods for creating objects that act like instances
of interfaces but allow for customized method invocation.
To create a proxy instance for some interface Foo
:
InvocationHandler handler = new MyInvocationHandler(...);
Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class<?>[] { Foo.class },
handler);
A proxy class is a class created at runtime that implements a specified
list of interfaces, known as proxy interfaces. A proxy instance
is an instance of a proxy class.
Each proxy instance has an associated invocation handler
object, which implements the interface InvocationHandler
.
A method invocation on a proxy instance through one of its proxy
interfaces will be dispatched to the invoke
method of the instance's invocation handler, passing the proxy
instance, a java.lang.reflect.Method
object identifying
the method that was invoked, and an array of type Object
containing the arguments. The invocation handler processes the
encoded method invocation as appropriate and the result that it
returns will be returned as the result of the method invocation on
the proxy instance.
A proxy class has the following properties:
"$Proxy"
should be, however, reserved for proxy classes.
java.lang.reflect.Proxy
.
getInterfaces
on its Class
object will return an array containing the same
list of interfaces (in the order specified at its creation), invoking
getMethods
on its Class
object will return
an array of Method
objects that include all of the
methods in those interfaces, and invoking getMethod
will
find methods in the proxy interfaces as would be expected.
java.security.ProtectionDomain
of a proxy class
is the same as that of system classes loaded by the bootstrap class
loader, such as java.lang.Object
, because the code for a
proxy class is generated by trusted system code. This protection
domain will typically be granted java.security.AllPermission
.
Proxy.isProxyClass
method can be used
to determine if a given class is a proxy class.
A proxy instance has the following properties:
proxy
and one of the
interfaces, Foo
, implemented by its proxy class, the
following expression will return true:
proxy instanceof Foo
and the following cast operation will succeed (rather than throwing
a ClassCastException
):
(Foo) proxy
Proxy.getInvocationHandler
method
will return the invocation handler associated with the proxy instance
passed as its argument.
invoke
method as described in the
documentation for that method.
InvocationHandler::invokeDefault
.
hashCode
,
equals
, or toString
methods declared in
java.lang.Object
on a proxy instance will be encoded and
dispatched to the invocation handler's invoke
method in
the same manner as interface method invocations are encoded and
dispatched, as described above. The declaring class of the
Method
object passed to invoke
will be
java.lang.Object
. Other public methods of a proxy
instance inherited from java.lang.Object
are not
overridden by a proxy class, so invocations of those methods behave
like they do for instances of java.lang.Object
.
Proxy#getProxyClass(ClassLoader, Class[])
or
Proxy#newProxyInstance(ClassLoader, Class[], InvocationHandler)
methods is specified as follows:
Note that if proxy interfaces with a mix of accessibilities -- for example, an exported public interface and a non-exported non-public interface -- are proxied by the same instance, then the proxy class's accessibility is governed by the least accessible proxy interface.
Note that it is possible for arbitrary code to obtain access to a proxy class
in an open package with setAccessible
,
whereas a proxy class in a non-open package is never accessible to
code outside the module of the proxy class.
Throughout this specification, a "non-exported package" refers to a package that is not exported to all modules, and a "non-open package" refers to a package that is not open to all modules. Specifically, these terms refer to a package that either is not exported/open by its containing module or is exported/open in a qualified fashion by its containing module.
A dynamic module is a named module generated at runtime. A proxy class
defined in a dynamic module is encapsulated and not accessible to any module.
Calling Constructor#newInstance(Object.
on a proxy class in
a dynamic module will throw IllegalAccessException
;
Proxy.newProxyInstance
method should be used instead.
A dynamic module can read the modules of all of the superinterfaces of a proxy
class and the modules of the classes and interfaces referenced by
all public method signatures of a proxy class. If a superinterface or
a referenced class or interface, say T
, is in a non-exported package,
the module of T
is updated to export the
package of T
to the dynamic module.
When two or more proxy interfaces contain a method with
the same name and parameter signature, the order of the proxy class's
interfaces becomes significant. When such a duplicate method
is invoked on a proxy instance, the Method
object passed
to the invocation handler will not necessarily be the one whose
declaring class is assignable from the reference type of the interface
that the proxy's method was invoked through. This limitation exists
because the corresponding method implementation in the generated proxy
class cannot determine which interface it was invoked through.
Therefore, when a duplicate method is invoked on a proxy instance,
the Method
object for the method in the foremost interface
that contains the method (either directly or inherited through a
superinterface) in the proxy class's list of interfaces is passed to
the invocation handler's invoke
method, regardless of the
reference type through which the method invocation occurred.
If a proxy interface contains a method with the same name and
parameter signature as the hashCode
, equals
,
or toString
methods of java.lang.Object
,
when such a method is invoked on a proxy instance, the
Method
object passed to the invocation handler will have
java.lang.Object
as its declaring class. In other words,
the public, non-final methods of java.lang.Object
logically precede all of the proxy interfaces for the determination of
which Method
object to pass to the invocation handler.
Note also that when a duplicate method is dispatched to an
invocation handler, the invoke
method may only throw
checked exception types that are assignable to one of the exception
types in the throws
clause of the method in all of
the proxy interfaces that it can be invoked through. If the
invoke
method throws a checked exception that is not
assignable to any of the exception types declared by the method in one
of the proxy interfaces that it can be invoked through, then an
unchecked UndeclaredThrowableException
will be thrown by
the invocation on the proxy instance. This restriction means that not
all of the exception types returned by invoking
getExceptionTypes
on the Method
object
passed to the invoke
method can necessarily be thrown
successfully by the invoke
method.
InvocationHandler
Modifier and Type | Class and Description |
---|---|
pack-priv static class | Proxy.
Internal exception type to wrap the exception thrown by the default method so that it can distinguish CCE and NPE thrown due to the arguments incompatible with the method signature. |
private static class | Proxy.
Builder for a proxy class. |
Modifier and Type | Field and Description |
---|---|
private static final Class | constructorParams
parameter types of a proxy class constructor |
private static final ClassValue | DEFAULT_METHODS_MAP
A cache of Method -> MethodHandle for default methods. |
pack-priv static final Object[] | |
protected InvocationHandler | h
the invocation handler for this proxy instance. |
private static final String | |
private static final ClassLoaderValue | proxyCache
a cache of proxy constructors with
|
private static final long |
Access | Constructor and Description |
---|---|
private | |
protected | Proxy(InvocationHandler
the invocation handler for this proxy instance h)Constructs a new |
Modifier and Type | Method and Description |
---|---|
private static void | |
private static void | |
pack-priv static MethodHandle | |
private static ConcurrentHashMap | |
private static Class | findProxyInterfaceOrElseThrow(Class<?> proxyClass, Method method)
Finds the first proxy interface that declares the given method directly or indirectly. |
public static InvocationHandler | Returns: the invocation handler for the proxy instancethe proxy instance to return the invocation handler for proxy)Returns the invocation handler for the specified proxy instance. |
private static ClassLoader | |
public static Class | Returns: a proxy class that is defined in the specified class loader and that implements the specified interfacesthe class loader to define the proxy class loader, Class<?>... the list of interfaces for the proxy class
to implement interfaces)
Deprecated
Proxy classes generated in a named module are encapsulated
and not accessible to code outside its module.
Returns the |
private static Constructor | Returns: a Constructor of the proxy class taking singleInvocationHandler parameterpassed from a public-facing @CallerSensitive method if
SecurityManager is set or caller, ClassLoader null if there's no
SecurityManagerthe class loader to define the proxy class loader, Class<?>... the list of interfaces for the proxy class
to implement interfaces)Returns the |
pack-priv static Object | |
public static boolean | Returns: true if the class is a proxy class and
false otherwisethe class to test cl)Returns true if the given class is a proxy class. |
public static Object | Returns: a proxy instance with the specified invocation handler of a proxy class that is defined by the specified class loader and that implements the specified interfacesthe class loader to define the proxy class loader, Class<?>[] the list of interfaces for the proxy class
to implement interfaces, InvocationHandler the invocation handler to dispatch method invocations to h)Returns a proxy instance for the specified interfaces that dispatches method invocations to the specified invocation handler. |
private static Object | |
private static MethodHandles. | Returns: a lookup for proxy class of this proxy instanceThis method invokes the proxy's proxyClassLookup method to get a Lookup on the proxy class. |
constructorParams | back to summary |
---|---|
private static final Class<?>[] constructorParams parameter types of a proxy class constructor |
DEFAULT_METHODS_MAP | back to summary |
---|---|
private static final ClassValue<ConcurrentHashMap<Method, MethodHandle>> DEFAULT_METHODS_MAP A cache of Method -> MethodHandle for default methods. |
EMPTY_ARGS | back to summary |
---|---|
pack-priv static final Object[] EMPTY_ARGS |
h | back to summary |
---|---|
protected InvocationHandler h the invocation handler for this proxy instance.
|
PROXY_PACKAGE_PREFIX | back to summary |
---|---|
private static final String PROXY_PACKAGE_PREFIX |
proxyCache | back to summary |
---|---|
private static final ClassLoaderValue<Constructor<?>> proxyCache a cache of proxy constructors with
|
serialVersionUID | back to summary |
---|---|
private static final long serialVersionUID
|
Proxy | back to summary |
---|---|
private Proxy() Prohibits instantiation. |
Proxy | back to summary |
---|---|
protected Proxy(InvocationHandler h) Constructs a new
|
checkNewProxyPermission | back to summary |
---|---|
private static void checkNewProxyPermission(Class<?> caller, Class<?> proxyClass) |
checkProxyAccess | back to summary |
---|---|
private static void checkProxyAccess(Class<?> caller, ClassLoader loader, Class<?>... interfaces) |
defaultMethodHandle | back to summary |
---|---|
pack-priv static MethodHandle defaultMethodHandle(Class<? extends Proxy> proxyClass, Method method) |
defaultMethodMap | back to summary |
---|---|
private static ConcurrentHashMap |
findProxyInterfaceOrElseThrow | back to summary |
---|---|
private static Class Finds the first proxy interface that declares the given method directly or indirectly.
|
getInvocationHandler | back to summary |
---|---|
public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException Returns the invocation handler for the specified proxy instance.
|
getLoader | back to summary |
---|---|
private static ClassLoader getLoader(Module m) Returns the class loader for the given module.
|
getProxyClass | back to summary |
---|---|
public static Class Deprecated Proxy classes generated in a named module are encapsulated
and not accessible to code outside its module.
Returns the
|
getProxyConstructor | back to summary |
---|---|
private static Constructor Returns the
|
invokeDefault | back to summary |
---|---|
pack-priv static Object invokeDefault(Object proxy, Method method, Object[] args, Class<?> caller) throws Throwable |
isProxyClass | back to summary |
---|---|
public static boolean isProxyClass(Class<?> cl) Returns true if the given class is a proxy class. Implementation Note The reliability of this method is important for the ability
to use it to make security decisions, so its implementation should
not just test if the class in question extends
|
newProxyInstance | back to summary |
---|---|
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) Returns a proxy instance for the specified interfaces that dispatches method invocations to the specified invocation handler.
Note that the order of the specified proxy interfaces is significant: two requests for a proxy class with the same combination of interfaces but in a different order will result in two distinct proxy classes.
|
newProxyInstance | back to summary |
---|---|
private static Object newProxyInstance(Class<?> caller, Constructor<?> cons, InvocationHandler h) |
proxyClassLookup | back to summary |
---|---|
private static MethodHandles. This method invokes the proxy's proxyClassLookup method to get a Lookup on the proxy class.
|
Modifier and Type | Field and Description |
---|---|
private static final long | |
pack-priv static MethodHandle |
Access | Constructor and Description |
---|---|
pack-priv |
Modifier and Type | Method and Description |
---|---|
pack-priv static Object | |
pack-priv static MethodHandle |
serialVersionUID | back to summary |
---|---|
private static final long serialVersionUID Hides java. |
wrapMethodHandle | back to summary |
---|---|
pack-priv static MethodHandle wrapMethodHandle
|
InvocationException | back to summary |
---|---|
pack-priv InvocationException(Throwable cause) |
wrap | back to summary |
---|---|
pack-priv static Object wrap(Throwable cause) throws InvocationException Wraps given cause with InvocationException and throws it. |
wrapMH | back to summary |
---|---|
pack-priv static MethodHandle wrapMH() |
Modifier and Type | Class and Description |
---|---|
private static record |
Modifier and Type | Field and Description |
---|---|
private final Proxy. | |
private static final AtomicInteger | |
private static final String | |
private static final ClassLoaderValue | |
private final List | |
private static final JavaLangAccess | |
private static final AtomicLong | |
private static final String | |
private static final ClassLoaderValue |
Access | Constructor and Description |
---|---|
pack-priv | |
pack-priv |
Modifier and Type | Method and Description |
---|---|
private static void | |
private static void | |
pack-priv Constructor | |
private static Class | |
private static void | |
private static void | |
private static Module | |
private static Class | |
private static boolean | |
private static boolean | |
private static boolean | |
private static boolean | |
pack-priv static boolean | isProxyClass(Class<?> c)
Test if given class is a class defined by
|
private static Proxy. | proxyClassContext(ClassLoader loader, List<Class<?>> interfaces, Set<Class<?>> refTypes)
Returns the context for the generated proxy class, including the module and the package it belongs to and whether it is package-private. |
private static Set | |
private static String | |
pack-priv static void | |
private static void | validateProxyInterfaces(ClassLoader loader, List<Class<?>> interfaces, Set<Class<?>> refTypes)
Validate the given proxy interfaces and the given referenced types are visible to the defining loader. |
context | back to summary |
---|---|
private final Proxy. |
counter | back to summary |
---|---|
private static final AtomicInteger counter |
DEBUG | back to summary |
---|---|
private static final String DEBUG |
dynProxyModules | back to summary |
---|---|
private static final ClassLoaderValue<Module> dynProxyModules |
interfaces | back to summary |
---|---|
private final List<Class<?>> interfaces |
JLA | back to summary |
---|---|
private static final JavaLangAccess JLA |
nextUniqueNumber | back to summary |
---|---|
private static final AtomicLong nextUniqueNumber |
proxyClassNamePrefix | back to summary |
---|---|
private static final String proxyClassNamePrefix |
reverseProxyCache | back to summary |
---|---|
private static final ClassLoaderValue<Boolean> reverseProxyCache |
ProxyBuilder | back to summary |
---|---|
pack-priv ProxyBuilder(ClassLoader loader, List<Class<?>> interfaces) |
ProxyBuilder | back to summary |
---|---|
pack-priv ProxyBuilder(ClassLoader loader, Class<?> intf) |
addElementType | back to summary |
---|---|
private static void addElementType(HashSet<Class<?>> types, Class<?> cls) |
addElementTypes | back to summary |
---|---|
private static void addElementTypes(HashSet<Class<?>> types, Class<?>... classes) |
build | back to summary |
---|---|
pack-priv Constructor Generate a proxy class and return its proxy Constructor with accessible flag already set. If the target module does not have access to any interface types, IllegalAccessError will be thrown by the VM at defineClass time. Must call the checkProxyAccess method to perform permission checks before calling this.
|
defineProxyClass | back to summary |
---|---|
private static Class |
ensureAccess | back to summary |
---|---|
private static void ensureAccess(Module target, Class<?> c) |
ensureVisible | back to summary |
---|---|
private static void ensureVisible(ClassLoader ld, Class<?> c) |
getDynamicModule | back to summary |
---|---|
private static Module getDynamicModule(ClassLoader loader) |
getElementType | back to summary |
---|---|
private static Class |
isDebug | back to summary |
---|---|
private static boolean isDebug() |
isDebug | back to summary |
---|---|
private static boolean isDebug(String flag) |
isExportedType | back to summary |
---|---|
private static boolean isExportedType(Class<?> c) |
isPackagePrivateType | back to summary |
---|---|
private static boolean isPackagePrivateType(Class<?> c) |
isProxyClass | back to summary |
---|---|
pack-priv static boolean isProxyClass(Class<?> c) Test if given class is a class defined by
|
proxyClassContext | back to summary |
---|---|
private static Proxy. Returns the context for the generated proxy class, including the module and the package it belongs to and whether it is package-private. If any of proxy interface is package-private, then the proxy class is in the same package and module as the package-private interface. If all proxy interfaces are public and in exported packages, then the proxy class is in a dynamic module in an unconditionally exported package. If all proxy interfaces are public and at least one in a non-exported package, then the proxy class is in a dynamic module in a non-exported package. The package of proxy class is open to java.base for deep reflective access. Reads edge and qualified exports are added for dynamic module to access. |
referencedTypes | back to summary |
---|---|
private static Set |
toDetails | back to summary |
---|---|
private static String toDetails(Class<?> c) |
trace | back to summary |
---|---|
pack-priv static void trace(String cn, Module module, ClassLoader loader, List<Class<?>> interfaces) |
validateProxyInterfaces | back to summary |
---|---|
private static void validateProxyInterfaces(ClassLoader loader, List<Class<?>> interfaces, Set<Class<?>> refTypes) Validate the given proxy interfaces and the given referenced types are visible to the defining loader.
|
Modifier and Type | Field and Description |
---|---|
private final int | accessFlags
Record Component accessed by accessFlags(). |
private final Module | |
private final String | packageName
Record Component accessed by packageName(). |
Access | Constructor and Description |
---|---|
private |
Modifier and Type | Method and Description |
---|---|
public int | |
public final boolean | equals(Object
the reference object with which to compare. o)Implements abstract java. Indicates whether some other object is "equal to" this one. |
public final int | |
public Module | |
public String | |
public final String | toString()
Implements abstract java. Returns a string representation of the record. |
accessFlags | back to summary |
---|---|
private final int accessFlags Record Component accessed by accessFlags(). |
module | back to summary |
---|---|
private final Module module Record Component accessed by module(). |
packageName | back to summary |
---|---|
private final String packageName Record Component accessed by packageName(). |
ProxyClassContext | back to summary |
---|---|
private ProxyClassContext(Module module, String packageName, int accessFlags) |
accessFlags | back to summary |
---|---|
public int accessFlags() Record Component getter of accessFlags. |
equals | back to summary |
---|---|
public final boolean equals(Object o) Implements abstract java. Doc from java. Indicates whether some other object is "equal to" this one. In addition
to the general contract of R copy = new R(r.c1(), r.c2(), ..., r.cn());then it must be the case that r.equals(copy) .
|
hashCode | back to summary |
---|---|
public final int hashCode() Implements abstract java. Doc from java. Returns a hash code value for the record.
Obeys the general contract of
|
module | back to summary |
---|---|
public Module module() Record Component getter of module. |
packageName | back to summary |
---|---|
public String packageName() Record Component getter of packageName. |
toString | back to summary |
---|---|
public final String toString() Implements abstract java. Doc from java. Returns a string representation of the record.
In accordance with the general contract of In addition to this general contract, record classes must further participate in the invariant that any two records which are equal must produce equal strings. This invariant is necessarily relaxed in the rare case where corresponding equal component values might fail to produce equal strings for themselves.
|