emul/mini/src/main/java/java/lang/reflect/Proxy.java
branchjdk7-b147
changeset 601 5198affdb915
child 604 3fcc279c921b
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/emul/mini/src/main/java/java/lang/reflect/Proxy.java	Mon Jan 28 18:12:47 2013 +0100
     1.3 @@ -0,0 +1,666 @@
     1.4 +/*
     1.5 + * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Oracle designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Oracle in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 + * or visit www.oracle.com if you need additional information or have any
    1.26 + * questions.
    1.27 + */
    1.28 +
    1.29 +package java.lang.reflect;
    1.30 +
    1.31 +import java.lang.ref.Reference;
    1.32 +import java.lang.ref.WeakReference;
    1.33 +import java.util.Arrays;
    1.34 +import java.util.Collections;
    1.35 +import java.util.HashMap;
    1.36 +import java.util.HashSet;
    1.37 +import java.util.Map;
    1.38 +import java.util.Set;
    1.39 +import java.util.List;
    1.40 +import java.util.WeakHashMap;
    1.41 +import sun.misc.ProxyGenerator;
    1.42 +
    1.43 +/**
    1.44 + * {@code Proxy} provides static methods for creating dynamic proxy
    1.45 + * classes and instances, and it is also the superclass of all
    1.46 + * dynamic proxy classes created by those methods.
    1.47 + *
    1.48 + * <p>To create a proxy for some interface {@code Foo}:
    1.49 + * <pre>
    1.50 + *     InvocationHandler handler = new MyInvocationHandler(...);
    1.51 + *     Class proxyClass = Proxy.getProxyClass(
    1.52 + *         Foo.class.getClassLoader(), new Class[] { Foo.class });
    1.53 + *     Foo f = (Foo) proxyClass.
    1.54 + *         getConstructor(new Class[] { InvocationHandler.class }).
    1.55 + *         newInstance(new Object[] { handler });
    1.56 + * </pre>
    1.57 + * or more simply:
    1.58 + * <pre>
    1.59 + *     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
    1.60 + *                                          new Class[] { Foo.class },
    1.61 + *                                          handler);
    1.62 + * </pre>
    1.63 + *
    1.64 + * <p>A <i>dynamic proxy class</i> (simply referred to as a <i>proxy
    1.65 + * class</i> below) is a class that implements a list of interfaces
    1.66 + * specified at runtime when the class is created, with behavior as
    1.67 + * described below.
    1.68 + *
    1.69 + * A <i>proxy interface</i> is such an interface that is implemented
    1.70 + * by a proxy class.
    1.71 + *
    1.72 + * A <i>proxy instance</i> is an instance of a proxy class.
    1.73 + *
    1.74 + * Each proxy instance has an associated <i>invocation handler</i>
    1.75 + * object, which implements the interface {@link InvocationHandler}.
    1.76 + * A method invocation on a proxy instance through one of its proxy
    1.77 + * interfaces will be dispatched to the {@link InvocationHandler#invoke
    1.78 + * invoke} method of the instance's invocation handler, passing the proxy
    1.79 + * instance, a {@code java.lang.reflect.Method} object identifying
    1.80 + * the method that was invoked, and an array of type {@code Object}
    1.81 + * containing the arguments.  The invocation handler processes the
    1.82 + * encoded method invocation as appropriate and the result that it
    1.83 + * returns will be returned as the result of the method invocation on
    1.84 + * the proxy instance.
    1.85 + *
    1.86 + * <p>A proxy class has the following properties:
    1.87 + *
    1.88 + * <ul>
    1.89 + * <li>Proxy classes are public, final, and not abstract.
    1.90 + *
    1.91 + * <li>The unqualified name of a proxy class is unspecified.  The space
    1.92 + * of class names that begin with the string {@code "$Proxy"}
    1.93 + * should be, however, reserved for proxy classes.
    1.94 + *
    1.95 + * <li>A proxy class extends {@code java.lang.reflect.Proxy}.
    1.96 + *
    1.97 + * <li>A proxy class implements exactly the interfaces specified at its
    1.98 + * creation, in the same order.
    1.99 + *
   1.100 + * <li>If a proxy class implements a non-public interface, then it will
   1.101 + * be defined in the same package as that interface.  Otherwise, the
   1.102 + * package of a proxy class is also unspecified.  Note that package
   1.103 + * sealing will not prevent a proxy class from being successfully defined
   1.104 + * in a particular package at runtime, and neither will classes already
   1.105 + * defined by the same class loader and the same package with particular
   1.106 + * signers.
   1.107 + *
   1.108 + * <li>Since a proxy class implements all of the interfaces specified at
   1.109 + * its creation, invoking {@code getInterfaces} on its
   1.110 + * {@code Class} object will return an array containing the same
   1.111 + * list of interfaces (in the order specified at its creation), invoking
   1.112 + * {@code getMethods} on its {@code Class} object will return
   1.113 + * an array of {@code Method} objects that include all of the
   1.114 + * methods in those interfaces, and invoking {@code getMethod} will
   1.115 + * find methods in the proxy interfaces as would be expected.
   1.116 + *
   1.117 + * <li>The {@link Proxy#isProxyClass Proxy.isProxyClass} method will
   1.118 + * return true if it is passed a proxy class-- a class returned by
   1.119 + * {@code Proxy.getProxyClass} or the class of an object returned by
   1.120 + * {@code Proxy.newProxyInstance}-- and false otherwise.
   1.121 + *
   1.122 + * <li>The {@code java.security.ProtectionDomain} of a proxy class
   1.123 + * is the same as that of system classes loaded by the bootstrap class
   1.124 + * loader, such as {@code java.lang.Object}, because the code for a
   1.125 + * proxy class is generated by trusted system code.  This protection
   1.126 + * domain will typically be granted
   1.127 + * {@code java.security.AllPermission}.
   1.128 + *
   1.129 + * <li>Each proxy class has one public constructor that takes one argument,
   1.130 + * an implementation of the interface {@link InvocationHandler}, to set
   1.131 + * the invocation handler for a proxy instance.  Rather than having to use
   1.132 + * the reflection API to access the public constructor, a proxy instance
   1.133 + * can be also be created by calling the {@link Proxy#newProxyInstance
   1.134 + * Proxy.newProxyInstance} method, which combines the actions of calling
   1.135 + * {@link Proxy#getProxyClass Proxy.getProxyClass} with invoking the
   1.136 + * constructor with an invocation handler.
   1.137 + * </ul>
   1.138 + *
   1.139 + * <p>A proxy instance has the following properties:
   1.140 + *
   1.141 + * <ul>
   1.142 + * <li>Given a proxy instance {@code proxy} and one of the
   1.143 + * interfaces implemented by its proxy class {@code Foo}, the
   1.144 + * following expression will return true:
   1.145 + * <pre>
   1.146 + *     {@code proxy instanceof Foo}
   1.147 + * </pre>
   1.148 + * and the following cast operation will succeed (rather than throwing
   1.149 + * a {@code ClassCastException}):
   1.150 + * <pre>
   1.151 + *     {@code (Foo) proxy}
   1.152 + * </pre>
   1.153 + *
   1.154 + * <li>Each proxy instance has an associated invocation handler, the one
   1.155 + * that was passed to its constructor.  The static
   1.156 + * {@link Proxy#getInvocationHandler Proxy.getInvocationHandler} method
   1.157 + * will return the invocation handler associated with the proxy instance
   1.158 + * passed as its argument.
   1.159 + *
   1.160 + * <li>An interface method invocation on a proxy instance will be
   1.161 + * encoded and dispatched to the invocation handler's {@link
   1.162 + * InvocationHandler#invoke invoke} method as described in the
   1.163 + * documentation for that method.
   1.164 + *
   1.165 + * <li>An invocation of the {@code hashCode},
   1.166 + * {@code equals}, or {@code toString} methods declared in
   1.167 + * {@code java.lang.Object} on a proxy instance will be encoded and
   1.168 + * dispatched to the invocation handler's {@code invoke} method in
   1.169 + * the same manner as interface method invocations are encoded and
   1.170 + * dispatched, as described above.  The declaring class of the
   1.171 + * {@code Method} object passed to {@code invoke} will be
   1.172 + * {@code java.lang.Object}.  Other public methods of a proxy
   1.173 + * instance inherited from {@code java.lang.Object} are not
   1.174 + * overridden by a proxy class, so invocations of those methods behave
   1.175 + * like they do for instances of {@code java.lang.Object}.
   1.176 + * </ul>
   1.177 + *
   1.178 + * <h3>Methods Duplicated in Multiple Proxy Interfaces</h3>
   1.179 + *
   1.180 + * <p>When two or more interfaces of a proxy class contain a method with
   1.181 + * the same name and parameter signature, the order of the proxy class's
   1.182 + * interfaces becomes significant.  When such a <i>duplicate method</i>
   1.183 + * is invoked on a proxy instance, the {@code Method} object passed
   1.184 + * to the invocation handler will not necessarily be the one whose
   1.185 + * declaring class is assignable from the reference type of the interface
   1.186 + * that the proxy's method was invoked through.  This limitation exists
   1.187 + * because the corresponding method implementation in the generated proxy
   1.188 + * class cannot determine which interface it was invoked through.
   1.189 + * Therefore, when a duplicate method is invoked on a proxy instance,
   1.190 + * the {@code Method} object for the method in the foremost interface
   1.191 + * that contains the method (either directly or inherited through a
   1.192 + * superinterface) in the proxy class's list of interfaces is passed to
   1.193 + * the invocation handler's {@code invoke} method, regardless of the
   1.194 + * reference type through which the method invocation occurred.
   1.195 + *
   1.196 + * <p>If a proxy interface contains a method with the same name and
   1.197 + * parameter signature as the {@code hashCode}, {@code equals},
   1.198 + * or {@code toString} methods of {@code java.lang.Object},
   1.199 + * when such a method is invoked on a proxy instance, the
   1.200 + * {@code Method} object passed to the invocation handler will have
   1.201 + * {@code java.lang.Object} as its declaring class.  In other words,
   1.202 + * the public, non-final methods of {@code java.lang.Object}
   1.203 + * logically precede all of the proxy interfaces for the determination of
   1.204 + * which {@code Method} object to pass to the invocation handler.
   1.205 + *
   1.206 + * <p>Note also that when a duplicate method is dispatched to an
   1.207 + * invocation handler, the {@code invoke} method may only throw
   1.208 + * checked exception types that are assignable to one of the exception
   1.209 + * types in the {@code throws} clause of the method in <i>all</i> of
   1.210 + * the proxy interfaces that it can be invoked through.  If the
   1.211 + * {@code invoke} method throws a checked exception that is not
   1.212 + * assignable to any of the exception types declared by the method in one
   1.213 + * of the proxy interfaces that it can be invoked through, then an
   1.214 + * unchecked {@code UndeclaredThrowableException} will be thrown by
   1.215 + * the invocation on the proxy instance.  This restriction means that not
   1.216 + * all of the exception types returned by invoking
   1.217 + * {@code getExceptionTypes} on the {@code Method} object
   1.218 + * passed to the {@code invoke} method can necessarily be thrown
   1.219 + * successfully by the {@code invoke} method.
   1.220 + *
   1.221 + * @author      Peter Jones
   1.222 + * @see         InvocationHandler
   1.223 + * @since       1.3
   1.224 + */
   1.225 +public class Proxy implements java.io.Serializable {
   1.226 +
   1.227 +    private static final long serialVersionUID = -2222568056686623797L;
   1.228 +
   1.229 +    /** prefix for all proxy class names */
   1.230 +    private final static String proxyClassNamePrefix = "$Proxy";
   1.231 +
   1.232 +    /** parameter types of a proxy class constructor */
   1.233 +    private final static Class[] constructorParams =
   1.234 +        { InvocationHandler.class };
   1.235 +
   1.236 +    /** maps a class loader to the proxy class cache for that loader */
   1.237 +    private static Map<ClassLoader, Map<List<String>, Object>> loaderToCache
   1.238 +        = new WeakHashMap<>();
   1.239 +
   1.240 +    /** marks that a particular proxy class is currently being generated */
   1.241 +    private static Object pendingGenerationMarker = new Object();
   1.242 +
   1.243 +    /** next number to use for generation of unique proxy class names */
   1.244 +    private static long nextUniqueNumber = 0;
   1.245 +    private static Object nextUniqueNumberLock = new Object();
   1.246 +
   1.247 +    /** set of all generated proxy classes, for isProxyClass implementation */
   1.248 +    private static Map<Class<?>, Void> proxyClasses =
   1.249 +        Collections.synchronizedMap(new WeakHashMap<Class<?>, Void>());
   1.250 +
   1.251 +    /**
   1.252 +     * the invocation handler for this proxy instance.
   1.253 +     * @serial
   1.254 +     */
   1.255 +    protected InvocationHandler h;
   1.256 +
   1.257 +    /**
   1.258 +     * Prohibits instantiation.
   1.259 +     */
   1.260 +    private Proxy() {
   1.261 +    }
   1.262 +
   1.263 +    /**
   1.264 +     * Constructs a new {@code Proxy} instance from a subclass
   1.265 +     * (typically, a dynamic proxy class) with the specified value
   1.266 +     * for its invocation handler.
   1.267 +     *
   1.268 +     * @param   h the invocation handler for this proxy instance
   1.269 +     */
   1.270 +    protected Proxy(InvocationHandler h) {
   1.271 +        this.h = h;
   1.272 +    }
   1.273 +
   1.274 +    /**
   1.275 +     * Returns the {@code java.lang.Class} object for a proxy class
   1.276 +     * given a class loader and an array of interfaces.  The proxy class
   1.277 +     * will be defined by the specified class loader and will implement
   1.278 +     * all of the supplied interfaces.  If a proxy class for the same
   1.279 +     * permutation of interfaces has already been defined by the class
   1.280 +     * loader, then the existing proxy class will be returned; otherwise,
   1.281 +     * a proxy class for those interfaces will be generated dynamically
   1.282 +     * and defined by the class loader.
   1.283 +     *
   1.284 +     * <p>There are several restrictions on the parameters that may be
   1.285 +     * passed to {@code Proxy.getProxyClass}:
   1.286 +     *
   1.287 +     * <ul>
   1.288 +     * <li>All of the {@code Class} objects in the
   1.289 +     * {@code interfaces} array must represent interfaces, not
   1.290 +     * classes or primitive types.
   1.291 +     *
   1.292 +     * <li>No two elements in the {@code interfaces} array may
   1.293 +     * refer to identical {@code Class} objects.
   1.294 +     *
   1.295 +     * <li>All of the interface types must be visible by name through the
   1.296 +     * specified class loader.  In other words, for class loader
   1.297 +     * {@code cl} and every interface {@code i}, the following
   1.298 +     * expression must be true:
   1.299 +     * <pre>
   1.300 +     *     Class.forName(i.getName(), false, cl) == i
   1.301 +     * </pre>
   1.302 +     *
   1.303 +     * <li>All non-public interfaces must be in the same package;
   1.304 +     * otherwise, it would not be possible for the proxy class to
   1.305 +     * implement all of the interfaces, regardless of what package it is
   1.306 +     * defined in.
   1.307 +     *
   1.308 +     * <li>For any set of member methods of the specified interfaces
   1.309 +     * that have the same signature:
   1.310 +     * <ul>
   1.311 +     * <li>If the return type of any of the methods is a primitive
   1.312 +     * type or void, then all of the methods must have that same
   1.313 +     * return type.
   1.314 +     * <li>Otherwise, one of the methods must have a return type that
   1.315 +     * is assignable to all of the return types of the rest of the
   1.316 +     * methods.
   1.317 +     * </ul>
   1.318 +     *
   1.319 +     * <li>The resulting proxy class must not exceed any limits imposed
   1.320 +     * on classes by the virtual machine.  For example, the VM may limit
   1.321 +     * the number of interfaces that a class may implement to 65535; in
   1.322 +     * that case, the size of the {@code interfaces} array must not
   1.323 +     * exceed 65535.
   1.324 +     * </ul>
   1.325 +     *
   1.326 +     * <p>If any of these restrictions are violated,
   1.327 +     * {@code Proxy.getProxyClass} will throw an
   1.328 +     * {@code IllegalArgumentException}.  If the {@code interfaces}
   1.329 +     * array argument or any of its elements are {@code null}, a
   1.330 +     * {@code NullPointerException} will be thrown.
   1.331 +     *
   1.332 +     * <p>Note that the order of the specified proxy interfaces is
   1.333 +     * significant: two requests for a proxy class with the same combination
   1.334 +     * of interfaces but in a different order will result in two distinct
   1.335 +     * proxy classes.
   1.336 +     *
   1.337 +     * @param   loader the class loader to define the proxy class
   1.338 +     * @param   interfaces the list of interfaces for the proxy class
   1.339 +     *          to implement
   1.340 +     * @return  a proxy class that is defined in the specified class loader
   1.341 +     *          and that implements the specified interfaces
   1.342 +     * @throws  IllegalArgumentException if any of the restrictions on the
   1.343 +     *          parameters that may be passed to {@code getProxyClass}
   1.344 +     *          are violated
   1.345 +     * @throws  NullPointerException if the {@code interfaces} array
   1.346 +     *          argument or any of its elements are {@code null}
   1.347 +     */
   1.348 +    public static Class<?> getProxyClass(ClassLoader loader,
   1.349 +                                         Class<?>... interfaces)
   1.350 +        throws IllegalArgumentException
   1.351 +    {
   1.352 +        if (interfaces.length > 65535) {
   1.353 +            throw new IllegalArgumentException("interface limit exceeded");
   1.354 +        }
   1.355 +
   1.356 +        Class<?> proxyClass = null;
   1.357 +
   1.358 +        /* collect interface names to use as key for proxy class cache */
   1.359 +        String[] interfaceNames = new String[interfaces.length];
   1.360 +
   1.361 +        // for detecting duplicates
   1.362 +        Set<Class<?>> interfaceSet = new HashSet<>();
   1.363 +
   1.364 +        for (int i = 0; i < interfaces.length; i++) {
   1.365 +            /*
   1.366 +             * Verify that the class loader resolves the name of this
   1.367 +             * interface to the same Class object.
   1.368 +             */
   1.369 +            String interfaceName = interfaces[i].getName();
   1.370 +            Class<?> interfaceClass = null;
   1.371 +            try {
   1.372 +                interfaceClass = Class.forName(interfaceName, false, loader);
   1.373 +            } catch (ClassNotFoundException e) {
   1.374 +            }
   1.375 +            if (interfaceClass != interfaces[i]) {
   1.376 +                throw new IllegalArgumentException(
   1.377 +                    interfaces[i] + " is not visible from class loader");
   1.378 +            }
   1.379 +
   1.380 +            /*
   1.381 +             * Verify that the Class object actually represents an
   1.382 +             * interface.
   1.383 +             */
   1.384 +            if (!interfaceClass.isInterface()) {
   1.385 +                throw new IllegalArgumentException(
   1.386 +                    interfaceClass.getName() + " is not an interface");
   1.387 +            }
   1.388 +
   1.389 +            /*
   1.390 +             * Verify that this interface is not a duplicate.
   1.391 +             */
   1.392 +            if (interfaceSet.contains(interfaceClass)) {
   1.393 +                throw new IllegalArgumentException(
   1.394 +                    "repeated interface: " + interfaceClass.getName());
   1.395 +            }
   1.396 +            interfaceSet.add(interfaceClass);
   1.397 +
   1.398 +            interfaceNames[i] = interfaceName;
   1.399 +        }
   1.400 +
   1.401 +        /*
   1.402 +         * Using string representations of the proxy interfaces as
   1.403 +         * keys in the proxy class cache (instead of their Class
   1.404 +         * objects) is sufficient because we require the proxy
   1.405 +         * interfaces to be resolvable by name through the supplied
   1.406 +         * class loader, and it has the advantage that using a string
   1.407 +         * representation of a class makes for an implicit weak
   1.408 +         * reference to the class.
   1.409 +         */
   1.410 +        List<String> key = Arrays.asList(interfaceNames);
   1.411 +
   1.412 +        /*
   1.413 +         * Find or create the proxy class cache for the class loader.
   1.414 +         */
   1.415 +        Map<List<String>, Object> cache;
   1.416 +        synchronized (loaderToCache) {
   1.417 +            cache = loaderToCache.get(loader);
   1.418 +            if (cache == null) {
   1.419 +                cache = new HashMap<>();
   1.420 +                loaderToCache.put(loader, cache);
   1.421 +            }
   1.422 +            /*
   1.423 +             * This mapping will remain valid for the duration of this
   1.424 +             * method, without further synchronization, because the mapping
   1.425 +             * will only be removed if the class loader becomes unreachable.
   1.426 +             */
   1.427 +        }
   1.428 +
   1.429 +        /*
   1.430 +         * Look up the list of interfaces in the proxy class cache using
   1.431 +         * the key.  This lookup will result in one of three possible
   1.432 +         * kinds of values:
   1.433 +         *     null, if there is currently no proxy class for the list of
   1.434 +         *         interfaces in the class loader,
   1.435 +         *     the pendingGenerationMarker object, if a proxy class for the
   1.436 +         *         list of interfaces is currently being generated,
   1.437 +         *     or a weak reference to a Class object, if a proxy class for
   1.438 +         *         the list of interfaces has already been generated.
   1.439 +         */
   1.440 +        synchronized (cache) {
   1.441 +            /*
   1.442 +             * Note that we need not worry about reaping the cache for
   1.443 +             * entries with cleared weak references because if a proxy class
   1.444 +             * has been garbage collected, its class loader will have been
   1.445 +             * garbage collected as well, so the entire cache will be reaped
   1.446 +             * from the loaderToCache map.
   1.447 +             */
   1.448 +            do {
   1.449 +                Object value = cache.get(key);
   1.450 +                if (value instanceof Reference) {
   1.451 +                    proxyClass = (Class<?>) ((Reference) value).get();
   1.452 +                }
   1.453 +                if (proxyClass != null) {
   1.454 +                    // proxy class already generated: return it
   1.455 +                    return proxyClass;
   1.456 +                } else if (value == pendingGenerationMarker) {
   1.457 +                    // proxy class being generated: wait for it
   1.458 +                    try {
   1.459 +                        cache.wait();
   1.460 +                    } catch (InterruptedException e) {
   1.461 +                        /*
   1.462 +                         * The class generation that we are waiting for should
   1.463 +                         * take a small, bounded time, so we can safely ignore
   1.464 +                         * thread interrupts here.
   1.465 +                         */
   1.466 +                    }
   1.467 +                    continue;
   1.468 +                } else {
   1.469 +                    /*
   1.470 +                     * No proxy class for this list of interfaces has been
   1.471 +                     * generated or is being generated, so we will go and
   1.472 +                     * generate it now.  Mark it as pending generation.
   1.473 +                     */
   1.474 +                    cache.put(key, pendingGenerationMarker);
   1.475 +                    break;
   1.476 +                }
   1.477 +            } while (true);
   1.478 +        }
   1.479 +
   1.480 +        try {
   1.481 +            String proxyPkg = null;     // package to define proxy class in
   1.482 +
   1.483 +            /*
   1.484 +             * Record the package of a non-public proxy interface so that the
   1.485 +             * proxy class will be defined in the same package.  Verify that
   1.486 +             * all non-public proxy interfaces are in the same package.
   1.487 +             */
   1.488 +            for (int i = 0; i < interfaces.length; i++) {
   1.489 +                int flags = interfaces[i].getModifiers();
   1.490 +                if (!Modifier.isPublic(flags)) {
   1.491 +                    String name = interfaces[i].getName();
   1.492 +                    int n = name.lastIndexOf('.');
   1.493 +                    String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
   1.494 +                    if (proxyPkg == null) {
   1.495 +                        proxyPkg = pkg;
   1.496 +                    } else if (!pkg.equals(proxyPkg)) {
   1.497 +                        throw new IllegalArgumentException(
   1.498 +                            "non-public interfaces from different packages");
   1.499 +                    }
   1.500 +                }
   1.501 +            }
   1.502 +
   1.503 +            if (proxyPkg == null) {     // if no non-public proxy interfaces,
   1.504 +                proxyPkg = "";          // use the unnamed package
   1.505 +            }
   1.506 +
   1.507 +            {
   1.508 +                /*
   1.509 +                 * Choose a name for the proxy class to generate.
   1.510 +                 */
   1.511 +                long num;
   1.512 +                synchronized (nextUniqueNumberLock) {
   1.513 +                    num = nextUniqueNumber++;
   1.514 +                }
   1.515 +                String proxyName = proxyPkg + proxyClassNamePrefix + num;
   1.516 +                /*
   1.517 +                 * Verify that the class loader hasn't already
   1.518 +                 * defined a class with the chosen name.
   1.519 +                 */
   1.520 +
   1.521 +                /*
   1.522 +                 * Generate the specified proxy class.
   1.523 +                 */
   1.524 +                byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
   1.525 +                    proxyName, interfaces);
   1.526 +                try {
   1.527 +                    proxyClass = defineClass0(loader, proxyName,
   1.528 +                        proxyClassFile, 0, proxyClassFile.length);
   1.529 +                } catch (ClassFormatError e) {
   1.530 +                    /*
   1.531 +                     * A ClassFormatError here means that (barring bugs in the
   1.532 +                     * proxy class generation code) there was some other
   1.533 +                     * invalid aspect of the arguments supplied to the proxy
   1.534 +                     * class creation (such as virtual machine limitations
   1.535 +                     * exceeded).
   1.536 +                     */
   1.537 +                    throw new IllegalArgumentException(e.toString());
   1.538 +                }
   1.539 +            }
   1.540 +            // add to set of all generated proxy classes, for isProxyClass
   1.541 +            proxyClasses.put(proxyClass, null);
   1.542 +
   1.543 +        } finally {
   1.544 +            /*
   1.545 +             * We must clean up the "pending generation" state of the proxy
   1.546 +             * class cache entry somehow.  If a proxy class was successfully
   1.547 +             * generated, store it in the cache (with a weak reference);
   1.548 +             * otherwise, remove the reserved entry.  In all cases, notify
   1.549 +             * all waiters on reserved entries in this cache.
   1.550 +             */
   1.551 +            synchronized (cache) {
   1.552 +                if (proxyClass != null) {
   1.553 +                    cache.put(key, new WeakReference<Class<?>>(proxyClass));
   1.554 +                } else {
   1.555 +                    cache.remove(key);
   1.556 +                }
   1.557 +                cache.notifyAll();
   1.558 +            }
   1.559 +        }
   1.560 +        return proxyClass;
   1.561 +    }
   1.562 +
   1.563 +    /**
   1.564 +     * Returns an instance of a proxy class for the specified interfaces
   1.565 +     * that dispatches method invocations to the specified invocation
   1.566 +     * handler.  This method is equivalent to:
   1.567 +     * <pre>
   1.568 +     *     Proxy.getProxyClass(loader, interfaces).
   1.569 +     *         getConstructor(new Class[] { InvocationHandler.class }).
   1.570 +     *         newInstance(new Object[] { handler });
   1.571 +     * </pre>
   1.572 +     *
   1.573 +     * <p>{@code Proxy.newProxyInstance} throws
   1.574 +     * {@code IllegalArgumentException} for the same reasons that
   1.575 +     * {@code Proxy.getProxyClass} does.
   1.576 +     *
   1.577 +     * @param   loader the class loader to define the proxy class
   1.578 +     * @param   interfaces the list of interfaces for the proxy class
   1.579 +     *          to implement
   1.580 +     * @param   h the invocation handler to dispatch method invocations to
   1.581 +     * @return  a proxy instance with the specified invocation handler of a
   1.582 +     *          proxy class that is defined by the specified class loader
   1.583 +     *          and that implements the specified interfaces
   1.584 +     * @throws  IllegalArgumentException if any of the restrictions on the
   1.585 +     *          parameters that may be passed to {@code getProxyClass}
   1.586 +     *          are violated
   1.587 +     * @throws  NullPointerException if the {@code interfaces} array
   1.588 +     *          argument or any of its elements are {@code null}, or
   1.589 +     *          if the invocation handler, {@code h}, is
   1.590 +     *          {@code null}
   1.591 +     */
   1.592 +    public static Object newProxyInstance(ClassLoader loader,
   1.593 +                                          Class<?>[] interfaces,
   1.594 +                                          InvocationHandler h)
   1.595 +        throws IllegalArgumentException
   1.596 +    {
   1.597 +        if (h == null) {
   1.598 +            throw new NullPointerException();
   1.599 +        }
   1.600 +
   1.601 +        /*
   1.602 +         * Look up or generate the designated proxy class.
   1.603 +         */
   1.604 +        Class<?> cl = getProxyClass(loader, interfaces);
   1.605 +
   1.606 +        /*
   1.607 +         * Invoke its constructor with the designated invocation handler.
   1.608 +         */
   1.609 +        try {
   1.610 +            Constructor cons = cl.getConstructor(constructorParams);
   1.611 +            return cons.newInstance(new Object[] { h });
   1.612 +        } catch (NoSuchMethodException e) {
   1.613 +            throw new InternalError(e.toString());
   1.614 +        } catch (IllegalAccessException e) {
   1.615 +            throw new InternalError(e.toString());
   1.616 +        } catch (InstantiationException e) {
   1.617 +            throw new InternalError(e.toString());
   1.618 +        } catch (InvocationTargetException e) {
   1.619 +            throw new InternalError(e.toString());
   1.620 +        }
   1.621 +    }
   1.622 +
   1.623 +    /**
   1.624 +     * Returns true if and only if the specified class was dynamically
   1.625 +     * generated to be a proxy class using the {@code getProxyClass}
   1.626 +     * method or the {@code newProxyInstance} method.
   1.627 +     *
   1.628 +     * <p>The reliability of this method is important for the ability
   1.629 +     * to use it to make security decisions, so its implementation should
   1.630 +     * not just test if the class in question extends {@code Proxy}.
   1.631 +     *
   1.632 +     * @param   cl the class to test
   1.633 +     * @return  {@code true} if the class is a proxy class and
   1.634 +     *          {@code false} otherwise
   1.635 +     * @throws  NullPointerException if {@code cl} is {@code null}
   1.636 +     */
   1.637 +    public static boolean isProxyClass(Class<?> cl) {
   1.638 +        if (cl == null) {
   1.639 +            throw new NullPointerException();
   1.640 +        }
   1.641 +
   1.642 +        return proxyClasses.containsKey(cl);
   1.643 +    }
   1.644 +
   1.645 +    /**
   1.646 +     * Returns the invocation handler for the specified proxy instance.
   1.647 +     *
   1.648 +     * @param   proxy the proxy instance to return the invocation handler for
   1.649 +     * @return  the invocation handler for the proxy instance
   1.650 +     * @throws  IllegalArgumentException if the argument is not a
   1.651 +     *          proxy instance
   1.652 +     */
   1.653 +    public static InvocationHandler getInvocationHandler(Object proxy)
   1.654 +        throws IllegalArgumentException
   1.655 +    {
   1.656 +        /*
   1.657 +         * Verify that the object is actually a proxy instance.
   1.658 +         */
   1.659 +        if (!isProxyClass(proxy.getClass())) {
   1.660 +            throw new IllegalArgumentException("not a proxy instance");
   1.661 +        }
   1.662 +
   1.663 +        Proxy p = (Proxy) proxy;
   1.664 +        return p.h;
   1.665 +    }
   1.666 +
   1.667 +    private static native Class defineClass0(ClassLoader loader, String name,
   1.668 +                                             byte[] b, int off, int len);
   1.669 +}