java.lang.reflect
Class Proxy
- Serializable
This class allows you to dynamically create an instance of any (or
even multiple) interfaces by reflection, and decide at runtime
how that instance will behave by giving it an appropriate
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.
Creation
To create a proxy for some interface Foo:
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);
Dynamic Proxy Classes
A dynamic proxy class is created at runtime, and has the following
properties:
- The class is
public
and final
,
and is neither abstract
nor an inner class. - The class has no canonical name (there is no formula you can use
to determine or generate its name), but begins with the
sequence "$Proxy". Abuse this knowledge at your own peril.
(For now, '$' in user identifiers is legal, but it may not
be that way forever. You weren't using '$' in your
identifiers, were you?)
- The class extends Proxy, and explicitly implements all the
interfaces specified at creation, in order (this is important
for determining how method invocation is resolved). Note that
a proxy class implements
Serializable
, at least
implicitly, since Proxy does, but true serial behavior
depends on using a serializable invocation handler as well. - If at least one interface is non-public, the proxy class
will be in the same package. Otherwise, the package is
unspecified. This will work even if the package is sealed
from user-generated classes, because Proxy classes are
generated by a trusted source. Meanwhile, the proxy class
belongs to the classloader you designated.
- Reflection works as expected:
Class.getInterfaces()
and
Class.getMethods()
work as they do on normal classes. - The method
isProxyClass(Class)
will distinguish between
true proxy classes and user extensions of this class. It only
returns true for classes created by getProxyClass(ClassLoader,)
. - The
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. - The proxy class contains a single constructor, which takes as
its only argument an
InvocationHandler
. The method
newProxyInstance(ClassLoader, Class[], InvocationHandler)
is shorthand to do the necessary reflection.
Proxy Instances
A proxy instance is an instance of a proxy class. It has the
following properties, many of which follow from the properties of a
proxy class listed above:
- For a proxy class with Foo listed as one of its interfaces, the
expression
proxy instanceof Foo
will return true,
and the expression (Foo) proxy
will succeed without
a ClassCastException
. - Each proxy instance has an invocation handler, which can be
accessed by
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.
Inheritance Issues
A proxy class may inherit a method from more than one interface.
The order in which interfaces are listed matters, because it determines
which reflected
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
.
Proxy(InvocationHandler handler) - Constructs a new Proxy from a subclass (usually a proxy class),
with the specified invocation handler.
|
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.
|
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.
|
clone , equals , extends Object> getClass , finalize , hashCode , notify , notifyAll , toString , wait , wait , wait |
h
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.
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.
handler
- the invocation handler, may be null if the subclass
is not a proxy class
getInvocationHandler
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)
.
proxy
- the proxy instance, must not be null
- the invocation handler, guaranteed non-null.
getProxyClass
public static Class> getProxyClass(ClassLoader loader,
Class>... interfaces)
Returns the proxy
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:
- 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.
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
- the Class object of the proxy class
isProxyClass
public 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
).
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 null
- true if the class represents a proxy class
newProxyInstance
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.
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
- a proxy instance implementing the specified interfaces
getProxyClass(ClassLoader, Class[])
, Class.getConstructor(Class[])
, Constructor.newInstance(Object[])
Proxy.java -- build a proxy class that implements reflected interfaces
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Classpath.
GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.
Linking this library statically or dynamically with other modules is
making a combined work based on this library. Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.
As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module. An independent module is a module which is not derived from
or based on this library. If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so. If you do not wish to do so, delete this
exception statement from your version.