java.lang.reflect
public class Proxy extends Object implements Serializable
InvocationHandler
. Proxy classes serialize specially, so
that the proxy object can be reused between VMs, without requiring
a persistent copy of the generated class code.
InvocationHandler handler = new MyInvocationHandler(...); Class proxyClass = Proxy.getProxyClass( Foo.class.getClassLoader(), new Class[] { Foo.class }); Foo f = (Foo) proxyClass .getConstructor(new Class[] { InvocationHandler.class }) .newInstance(new Object[] { handler });or more simply:
Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class[] { Foo.class }, handler);
public
and final
,
and is neither abstract
nor an inner class.Serializable
, at least
implicitly, since Proxy does, but true serial behavior
depends on using a serializable invocation handler as well.Class.getInterfaces()
and
Class.getMethods()
work as they do on normal classes.isProxyClass(Class)
will distinguish between
true proxy classes and user extensions of this class. It only
returns true for classes created by getProxyClass(java.lang.ClassLoader, java.lang.Class>...)
.ProtectionDomain
of a proxy class is the same as for
bootstrap classes, such as Object or Proxy, since it is created by
a trusted source. This protection domain will typically be granted
AllPermission
. But this is not a security
risk, since there are adequate permissions on reflection, which is
the only way to create an instance of the proxy class.InvocationHandler
. The method
newProxyInstance(ClassLoader, Class[], InvocationHandler)
is shorthand to do the necessary reflection.proxy instanceof Foo
will return true,
and the expression (Foo) proxy
will succeed without
a ClassCastException
.getInvocationHandler(Object)
. Any call
to an interface method, including Object.hashCode()
,
Object.equals(Object)
, or Object.toString()
,
but excluding the public final methods of Object, will be
encoded and passed to the InvocationHandler.invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
method of this handler.Method
object will be passed to the invocation
handler. This means that the dynamically generated class cannot
determine through which interface a method is being invoked.
In short, if a method is declared in Object (namely, hashCode,
equals, or toString), then Object will be used; otherwise, the
leftmost interface that inherits or declares a method will be used,
even if it has a more permissive throws clause than what the proxy
class is allowed. Thus, in the invocation handler, it is not always
safe to assume that every class listed in the throws clause of the
passed Method object can safely be thrown; fortunately, the Proxy
instance is robust enough to wrap all illegal checked exceptions in
UndeclaredThrowableException
.
InvocationHandler
,
UndeclaredThrowableException
,
Class
,
Serialized FormModifier and Type | Field and Description |
---|---|
protected InvocationHandler |
h
The invocation handler for this proxy instance.
|
Modifier | Constructor and Description |
---|---|
protected |
Proxy(InvocationHandler handler)
Constructs a new Proxy from a subclass (usually a proxy class),
with the specified invocation handler.
|
Modifier and Type | Method and Description |
---|---|
static InvocationHandler |
getInvocationHandler(Object proxy)
Returns the invocation handler for the given proxy instance.
|
static Class<?> |
getProxyClass(ClassLoader loader,
Class<?>... interfaces)
Returns the proxy
Class for the given ClassLoader and array
of interfaces, dynamically generating it if necessary. |
static boolean |
isProxyClass(Class<?> clazz)
Returns true if and only if the Class object is a dynamically created
proxy class (created by
getProxyClass or by the
syntactic sugar of newProxyInstance ). |
static Object |
newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler handler)
Combines several methods into one.
|
protected InvocationHandler h
protected Proxy(InvocationHandler handler)
handler
- the invocation handler, may be null if the subclass
is not a proxy classNullPointerException
- if handler is null and this is a proxy
instancepublic static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces)
Class
for the given ClassLoader and array
of interfaces, dynamically generating it if necessary.
There are several restrictions on this method, the violation of which will result in an IllegalArgumentException or NullPointerException:
Class.forName(i.getName(), false, loader) == i
must be true.Serializable
does not count against this limit).
Even though most VMs can theoretically have 65535
superinterfaces for a class, the actual limit is smaller
because a class's constant pool is limited to 65535 entries,
and not all entries can be interfaces.Note that different orders of interfaces produce distinct classes.
loader
- the class loader to define the proxy class in; null
implies the bootstrap class loaderinterfaces
- the array of interfaces the proxy class implements,
may be empty, but not nullIllegalArgumentException
- if the constraints above were
violated, except for problems with nullNullPointerException
- if `interfaces' is null or contains
a null entrypublic static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler)
Proxy.getProxyClass(loader, interfaces) .getConstructor(new Class[] {InvocationHandler.class}) .newInstance(new Object[] {handler});except that it will not fail with the normal problems caused by reflection. It can still fail for the same reasons documented in getProxyClass, or if handler is null.
loader
- the class loader to define the proxy class in; null
implies the bootstrap class loaderinterfaces
- the array of interfaces the proxy class implements,
may be empty, but not nullhandler
- the invocation handler, may not be nullIllegalArgumentException
- if the constraints for getProxyClass
were violated, except for problems with nullNullPointerException
- if `interfaces' is null or contains
a null entry, or if handler is nullgetProxyClass(ClassLoader, Class[])
,
Class.getConstructor(Class[])
,
Constructor.newInstance(Object[])
public static boolean isProxyClass(Class<?> clazz)
getProxyClass
or by the
syntactic sugar of newProxyInstance
).
This check is secure (in other words, it is not simply
clazz.getSuperclass() == Proxy.class
), it will not
be spoofed by non-proxy classes that extend Proxy.
clazz
- the class to check, must not be nullNullPointerException
- if clazz is nullpublic static InvocationHandler getInvocationHandler(Object proxy)
NOTE: We guarantee a non-null result if successful,
but Sun allows the creation of a proxy instance with a null
handler. See the comments for Proxy(InvocationHandler)
.
proxy
- the proxy instance, must not be nullIllegalArgumentException
- if
Proxy.isProxyClass(proxy.getClass())
returns false.NullPointerException
- if proxy is null