java.lang.reflect

Class Proxy

Implemented Interfaces:
Serializable

public class Proxy
extends Object
implements 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:

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:

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.

Since:
1.3
See Also:
InvocationHandler, UndeclaredThrowableException, Class, Serialized Form

Field Summary

protected InvocationHandler
h
The invocation handler for this proxy instance.

Constructor Summary

Proxy(InvocationHandler handler)
Constructs a new Proxy from a subclass (usually a proxy class), with the specified invocation handler.

Method Summary

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.

Methods inherited from class java.lang.Object

clone, equals, extends Object> getClass, finalize, hashCode, notify, notifyAll, toString, wait, wait, wait

Field Details

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.

Constructor Details

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

Method Details

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).

Parameters:
proxy - the proxy instance, must not be null
Returns:
the invocation handler, guaranteed non-null.
Throws:
IllegalArgumentException - if Proxy.isProxyClass(proxy.getClass()) returns false.
NullPointerException - if proxy is 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.

Parameters:
loader - the class loader to define the proxy class in; null implies the bootstrap class loader
interfaces - 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 null
NullPointerException - if `interfaces' is null or contains a null entry

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.

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

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.
Parameters:
loader - the class loader to define the proxy class in; null implies the bootstrap class loader
interfaces - the array of interfaces the proxy class implements, may be empty, but not null
handler - 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 null
NullPointerException - 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[])

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.