Prev Class | Next Class | Frames | No Frames |
Summary: Nested | Field | Method | Constr | Detail: Nested | Field | Method | Constr |
java.lang.Object
java.lang.reflect.Proxy
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(ClassLoader,)
.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(Object,Method,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
.
Field Summary | |
protected InvocationHandler |
|
Constructor Summary | |
|
Method Summary | |
static InvocationHandler |
|
static Class |
|
static boolean |
|
static Object |
|
Methods inherited from class java.lang.Object | |
clone , equals , extends Object> getClass , finalize , hashCode , notify , notifyAll , toString , wait , wait , wait |
protected InvocationHandler h
The invocation handler for this proxy instance. For Proxy, this field is unused, but it appears here in order to be serialized in all proxy classes. NOTE: This implementation is more secure for proxy classes than what Sun specifies. Sun does not require h to be immutable, but this means you could change h after the fact by reflection. However, by making h immutable, we may break non-proxy classes which extend Proxy.
protected Proxy(InvocationHandler handler)
Constructs a new Proxy from a subclass (usually a proxy class), with the specified invocation handler. NOTE: This throws a NullPointerException if you attempt to create a proxy instance with a null handler using reflection. This behavior is not yet specified by Sun; see Sun Bug 4487672.
- Parameters:
handler
- the invocation handler, may be null if the subclass is not a proxy class
- Throws:
NullPointerException
- if handler is null and this is a proxy instance
public static InvocationHandler getInvocationHandler(Object proxy)
Returns the invocation handler for the given proxy instance.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)
.
- Parameters:
proxy
- the proxy instance, must not be null
- Returns:
- the invocation handler, guaranteed non-null.
- Throws:
IllegalArgumentException
- ifProxy.isProxyClass(proxy.getClass())
returns false.NullPointerException
- if proxy is null
public static Class getProxyClass(ClassLoader loader, Class... interfaces)
Returns the proxyClass
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:
- All objects in `interfaces' must represent distinct interfaces. Classes, primitive types, null, and duplicates are forbidden.
- The interfaces must be visible in the specified ClassLoader. In other words, for each interface i:
Class.forName(i.getName(), false, loader) == i
must be true.- All non-public interfaces (if any) must reside in the same package, or the proxy class would be non-instantiable. If there are no non-public interfaces, the package of the proxy class is unspecified.
- All interfaces must be compatible - if two declare a method with the same name and parameters, the return type must be the same and the throws clause of the proxy class will be the maximal subset of subclasses of the throws clauses for each method that is overridden.
- VM constraints limit the number of interfaces a proxy class may directly implement (however, the indirect inheritance of
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.
- Parameters:
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 null
- Returns:
- the Class object of the proxy class
- Throws:
IllegalArgumentException
- if the constraints above were violated, except for problems with nullNullPointerException
- if `interfaces' is null or contains a null entry
public static boolean isProxyClass(Class clazz)
Returns true if and only if the Class object is a dynamically created proxy class (created bygetProxyClass
or by the syntactic sugar ofnewProxyInstance
).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.
- Parameters:
clazz
- the class to check, must not be null
- Returns:
- true if the class represents a proxy class
- Throws:
NullPointerException
- if clazz is null
public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler handler)
Combines several methods into one. This is equivalent to: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.
- Parameters:
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 null
- Returns:
- a proxy instance implementing the specified interfaces
- Throws:
IllegalArgumentException
- 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 null
- See Also:
getProxyClass(ClassLoader, Class[])
,Class.getConstructor(Class[])
,Constructor.newInstance(Object[])