FileDocCategorySizeDatePackage
Proxy.javaAPI DocAndroid 1.5 API12450Wed May 06 22:41:04 BST 2009java.lang.reflect

Proxy

public class Proxy extends Object implements Serializable
{@code Proxy} defines methods for creating dynamic proxy classes and instances. A proxy class implements a declared set of interfaces and delegates method invocations to an {@code InvocationHandler}.
see
InvocationHandler
since
Android 1.0

Fields Summary
private static final long
serialVersionUID
private static final Map
loaderCache
private static final Map
proxyCache
private static int
NextClassNameIndex
protected InvocationHandler
h
The invocation handler on which the method calls are dispatched.
Constructors Summary
private Proxy()

    
protected Proxy(InvocationHandler h)
Constructs a new {@code Proxy} instance with the specified invocation handler.

param
h the invocation handler for the newly created proxy
since
Android 1.0

        this.h = h;
    
Methods Summary
private static native voidconstructorPrototype(java.lang.reflect.InvocationHandler h)

private static native java.lang.ClassgenerateProxy(java.lang.String name, java.lang.Class[] interfaces, java.lang.ClassLoader loader)

public static java.lang.reflect.InvocationHandlergetInvocationHandler(java.lang.Object proxy)
Returns the invocation handler of the specified proxy instance.

param
proxy the proxy instance
return
the invocation handler of the specified proxy instance
throws
IllegalArgumentException if the supplied {@code proxy} is not a proxy object
since
Android 1.0


        if (isProxyClass(proxy.getClass())) {
            return ((Proxy) proxy).h;
        }

        throw new IllegalArgumentException(Msg.getString("K00f1")); //$NON-NLS-1$
    
public static java.lang.ClassgetProxyClass(java.lang.ClassLoader loader, java.lang.Class interfaces)
Returns the dynamically built {@code Class} for the specified interfaces. Creates a new {@code Class} when necessary. The order of the interfaces is relevant. Invocations of this method with the same interfaces but different order result in different generated classes. The interfaces must be visible from the supplied class loader; no duplicates are permitted. All non-public interfaces must be defined in the same package.

param
loader the class loader that will define the proxy class
param
interfaces an array of {@code Class} objects, each one identifying an interface that will be implemented by the returned proxy class
return
a proxy class that implements all of the interfaces referred to in the contents of {@code interfaces}
throws
IllegalArgumentException if any of the interface restrictions are violated
throws
NullPointerException if either {@code interfaces} or any of its elements are {@code null}
since
Android 1.0

        // BEGIN android-note
        // Changed parameter to be closer to the RI
        // END android-note
        // check that interfaces are a valid array of visible interfaces
        if (interfaces == null) {
            throw new NullPointerException();
        }
        String commonPackageName = null;
        for (int i = 0, length = interfaces.length; i < length; i++) {
            Class<?> next = interfaces[i];
            if (next == null) {
                throw new NullPointerException();
            }
            String name = next.getName();
            if (!next.isInterface()) {
                throw new IllegalArgumentException(Msg.getString("K00ed", name)); //$NON-NLS-1$
            }
            if (loader != next.getClassLoader()) {
                try {
                    if (next != Class.forName(name, false, loader)) {
                        throw new IllegalArgumentException(Msg.getString(
                                "K00ee", name)); //$NON-NLS-1$
                    }
                } catch (ClassNotFoundException ex) {
                    throw new IllegalArgumentException(Msg.getString("K00ee", //$NON-NLS-1$
                            name));
                }
            }
            for (int j = i + 1; j < length; j++) {
                if (next == interfaces[j]) {
                    throw new IllegalArgumentException(Msg.getString("K00ef", //$NON-NLS-1$
                            name));
                }
            }
            if (!Modifier.isPublic(next.getModifiers())) {
                int last = name.lastIndexOf('.");
                String p = last == -1 ? "" : name.substring(0, last); //$NON-NLS-1$
                if (commonPackageName == null) {
                    commonPackageName = p;
                } else if (!commonPackageName.equals(p)) {
                    throw new IllegalArgumentException(Msg.getString("K00f0")); //$NON-NLS-1$
                }
            }
        }

        // search cache for matching proxy class using the class loader
        synchronized (loaderCache) {
            Map<String, WeakReference<Class<?>>> interfaceCache = loaderCache
                    .get(loader);
            if (interfaceCache == null) {
                loaderCache
                        .put(
                                loader,
                                (interfaceCache = new HashMap<String, WeakReference<Class<?>>>()));
            }

            String interfaceKey = ""; //$NON-NLS-1$
            if (interfaces.length == 1) {
                interfaceKey = interfaces[0].getName();
            } else {
                StringBuilder names = new StringBuilder();
                for (int i = 0, length = interfaces.length; i < length; i++) {
                    names.append(interfaces[i].getName());
                    names.append(' ");
                }
                interfaceKey = names.toString();
            }

            Class<?> newClass;
            WeakReference<Class<?>> ref = interfaceCache.get(interfaceKey);
            if (ref == null) {
                String nextClassName = "$Proxy" + NextClassNameIndex++; //$NON-NLS-1$
                if (commonPackageName != null) {
                    nextClassName = commonPackageName + "." + nextClassName; //$NON-NLS-1$
                }
                // BEGIN android-changed
                //byte[] classFileBytes = ProxyClassFile.generateBytes(
                //        nextClassName, interfaces);
                // END android-changed
                if (loader == null) {
                    loader = ClassLoader.getSystemClassLoader();
                }
                // BEGIN android-changed
                //newClass = defineClassImpl(loader, nextClassName.replace('.',
                //        '/'), classFileBytes);
                newClass = generateProxy(nextClassName.replace('.", '/"),
                        interfaces, loader);
                // END android-changed
                // Need a weak reference to the class so it can
                // be unloaded if the class loader is discarded
                interfaceCache.put(interfaceKey, new WeakReference<Class<?>>(
                        newClass));
                synchronized (proxyCache) {
                    // the value is unused
                    proxyCache.put(newClass, ""); //$NON-NLS-1$
                }
            } else {
                newClass = ref.get();
            }
            return newClass;
        }
    
public static booleanisProxyClass(java.lang.Class cl)
Indicates whether or not the specified class is a dynamically generated proxy class.

param
cl the class
return
{@code true} if the class is a proxy class, {@code false} otherwise
throws
NullPointerException if the class is {@code null}
since
Android 1.0

        if (cl == null) {
            throw new NullPointerException();
        }
        synchronized (proxyCache) {
            return proxyCache.containsKey(cl);
        }
    
public static java.lang.ObjectnewProxyInstance(java.lang.ClassLoader loader, java.lang.Class[] interfaces, java.lang.reflect.InvocationHandler h)
Returns an instance of the dynamically built class for the specified interfaces. Method invocations on the returned instance are forwarded to the specified invocation handler. The interfaces must be visible from the supplied class loader; no duplicates are permitted. All non-public interfaces must be defined in the same package.

param
loader the class loader that will define the proxy class
param
interfaces an array of {@code Class} objects, each one identifying an interface that will be implemented by the returned proxy object
param
h the invocation handler that handles the dispatched method invocations
return
a new proxy object that delegates to the handler {@code h}
throws
IllegalArgumentException if any of the interface restrictions are violated
throws
NullPointerException if the interfaces or any of its elements are null
since
Android 1.0

        if (h == null) {
            throw new NullPointerException();
        }
        try {
            return getProxyClass(loader, interfaces).getConstructor(
                    new Class<?>[] { InvocationHandler.class }).newInstance(
                    new Object[] { h });
        } catch (NoSuchMethodException ex) {
            throw (InternalError) (new InternalError(ex.toString())
                    .initCause(ex));
        } catch (IllegalAccessException ex) {
            throw (InternalError) (new InternalError(ex.toString())
                    .initCause(ex));
        } catch (InstantiationException ex) {
            throw (InternalError) (new InternalError(ex.toString())
                    .initCause(ex));
        } catch (InvocationTargetException ex) {
            Throwable target = ex.getTargetException();
            throw (InternalError) (new InternalError(target.toString())
                    .initCause(target));
        }