Home | History | Annotate | Download | only in reflect
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
      4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      5  *
      6  * This code is free software; you can redistribute it and/or modify it
      7  * under the terms of the GNU General Public License version 2 only, as
      8  * published by the Free Software Foundation.  Oracle designates this
      9  * particular file as subject to the "Classpath" exception as provided
     10  * by Oracle in the LICENSE file that accompanied this code.
     11  *
     12  * This code is distributed in the hope that it will be useful, but WITHOUT
     13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     15  * version 2 for more details (a copy is included in the LICENSE file that
     16  * accompanied this code).
     17  *
     18  * You should have received a copy of the GNU General Public License version
     19  * 2 along with this work; if not, write to the Free Software Foundation,
     20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     21  *
     22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     23  * or visit www.oracle.com if you need additional information or have any
     24  * questions.
     25  */
     26 
     27 package java.lang.reflect;
     28 
     29 import java.lang.ref.Reference;
     30 import java.lang.ref.WeakReference;
     31 import java.security.AccessController;
     32 import java.security.Permission;
     33 import java.security.PrivilegedAction;
     34 import java.util.ArrayList;
     35 import java.util.Arrays;
     36 import java.util.Collections;
     37 import java.util.Comparator;
     38 import java.util.HashMap;
     39 import java.util.HashSet;
     40 import java.util.Map;
     41 import java.util.Set;
     42 import java.util.List;
     43 import java.util.WeakHashMap;
     44 import sun.reflect.CallerSensitive;
     45 import sun.reflect.misc.ReflectUtil;
     46 import sun.security.util.SecurityConstants;
     47 import libcore.util.EmptyArray;
     48 
     49 /**
     50  * {@code Proxy} provides static methods for creating dynamic proxy
     51  * classes and instances, and it is also the superclass of all
     52  * dynamic proxy classes created by those methods.
     53  *
     54  * <p>To create a proxy for some interface {@code Foo}:
     55  * <pre>
     56  *     InvocationHandler handler = new MyInvocationHandler(...);
     57  *     Class proxyClass = Proxy.getProxyClass(
     58  *         Foo.class.getClassLoader(), new Class[] { Foo.class });
     59  *     Foo f = (Foo) proxyClass.
     60  *         getConstructor(new Class[] { InvocationHandler.class }).
     61  *         newInstance(new Object[] { handler });
     62  * </pre>
     63  * or more simply:
     64  * <pre>
     65  *     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
     66  *                                          new Class[] { Foo.class },
     67  *                                          handler);
     68  * </pre>
     69  *
     70  * <p>A <i>dynamic proxy class</i> (simply referred to as a <i>proxy
     71  * class</i> below) is a class that implements a list of interfaces
     72  * specified at runtime when the class is created, with behavior as
     73  * described below.
     74  *
     75  * A <i>proxy interface</i> is such an interface that is implemented
     76  * by a proxy class.
     77  *
     78  * A <i>proxy instance</i> is an instance of a proxy class.
     79  *
     80  * Each proxy instance has an associated <i>invocation handler</i>
     81  * object, which implements the interface {@link InvocationHandler}.
     82  * A method invocation on a proxy instance through one of its proxy
     83  * interfaces will be dispatched to the {@link InvocationHandler#invoke
     84  * invoke} method of the instance's invocation handler, passing the proxy
     85  * instance, a {@code java.lang.reflect.Method} object identifying
     86  * the method that was invoked, and an array of type {@code Object}
     87  * containing the arguments.  The invocation handler processes the
     88  * encoded method invocation as appropriate and the result that it
     89  * returns will be returned as the result of the method invocation on
     90  * the proxy instance.
     91  *
     92  * <p>A proxy class has the following properties:
     93  *
     94  * <ul>
     95  * <li>Proxy classes are public, final, and not abstract.
     96  *
     97  * <li>The unqualified name of a proxy class is unspecified.  The space
     98  * of class names that begin with the string {@code "$Proxy"}
     99  * should be, however, reserved for proxy classes.
    100  *
    101  * <li>A proxy class extends {@code java.lang.reflect.Proxy}.
    102  *
    103  * <li>A proxy class implements exactly the interfaces specified at its
    104  * creation, in the same order.
    105  *
    106  * <li>If a proxy class implements a non-public interface, then it will
    107  * be defined in the same package as that interface.  Otherwise, the
    108  * package of a proxy class is also unspecified.  Note that package
    109  * sealing will not prevent a proxy class from being successfully defined
    110  * in a particular package at runtime, and neither will classes already
    111  * defined by the same class loader and the same package with particular
    112  * signers.
    113  *
    114  * <li>Since a proxy class implements all of the interfaces specified at
    115  * its creation, invoking {@code getInterfaces} on its
    116  * {@code Class} object will return an array containing the same
    117  * list of interfaces (in the order specified at its creation), invoking
    118  * {@code getMethods} on its {@code Class} object will return
    119  * an array of {@code Method} objects that include all of the
    120  * methods in those interfaces, and invoking {@code getMethod} will
    121  * find methods in the proxy interfaces as would be expected.
    122  *
    123  * <li>The {@link Proxy#isProxyClass Proxy.isProxyClass} method will
    124  * return true if it is passed a proxy class-- a class returned by
    125  * {@code Proxy.getProxyClass} or the class of an object returned by
    126  * {@code Proxy.newProxyInstance}-- and false otherwise.
    127  *
    128  * <li>The {@code java.security.ProtectionDomain} of a proxy class
    129  * is the same as that of system classes loaded by the bootstrap class
    130  * loader, such as {@code java.lang.Object}, because the code for a
    131  * proxy class is generated by trusted system code.  This protection
    132  * domain will typically be granted
    133  * {@code java.security.AllPermission}.
    134  *
    135  * <li>Each proxy class has one public constructor that takes one argument,
    136  * an implementation of the interface {@link InvocationHandler}, to set
    137  * the invocation handler for a proxy instance.  Rather than having to use
    138  * the reflection API to access the public constructor, a proxy instance
    139  * can be also be created by calling the {@link Proxy#newProxyInstance
    140  * Proxy.newProxyInstance} method, which combines the actions of calling
    141  * {@link Proxy#getProxyClass Proxy.getProxyClass} with invoking the
    142  * constructor with an invocation handler.
    143  * </ul>
    144  *
    145  * <p>A proxy instance has the following properties:
    146  *
    147  * <ul>
    148  * <li>Given a proxy instance {@code proxy} and one of the
    149  * interfaces implemented by its proxy class {@code Foo}, the
    150  * following expression will return true:
    151  * <pre>
    152  *     {@code proxy instanceof Foo}
    153  * </pre>
    154  * and the following cast operation will succeed (rather than throwing
    155  * a {@code ClassCastException}):
    156  * <pre>
    157  *     {@code (Foo) proxy}
    158  * </pre>
    159  *
    160  * <li>Each proxy instance has an associated invocation handler, the one
    161  * that was passed to its constructor.  The static
    162  * {@link Proxy#getInvocationHandler Proxy.getInvocationHandler} method
    163  * will return the invocation handler associated with the proxy instance
    164  * passed as its argument.
    165  *
    166  * <li>An interface method invocation on a proxy instance will be
    167  * encoded and dispatched to the invocation handler's {@link
    168  * InvocationHandler#invoke invoke} method as described in the
    169  * documentation for that method.
    170  *
    171  * <li>An invocation of the {@code hashCode},
    172  * {@code equals}, or {@code toString} methods declared in
    173  * {@code java.lang.Object} on a proxy instance will be encoded and
    174  * dispatched to the invocation handler's {@code invoke} method in
    175  * the same manner as interface method invocations are encoded and
    176  * dispatched, as described above.  The declaring class of the
    177  * {@code Method} object passed to {@code invoke} will be
    178  * {@code java.lang.Object}.  Other public methods of a proxy
    179  * instance inherited from {@code java.lang.Object} are not
    180  * overridden by a proxy class, so invocations of those methods behave
    181  * like they do for instances of {@code java.lang.Object}.
    182  * </ul>
    183  *
    184  * <h3>Methods Duplicated in Multiple Proxy Interfaces</h3>
    185  *
    186  * <p>When two or more interfaces of a proxy class contain a method with
    187  * the same name and parameter signature, the order of the proxy class's
    188  * interfaces becomes significant.  When such a <i>duplicate method</i>
    189  * is invoked on a proxy instance, the {@code Method} object passed
    190  * to the invocation handler will not necessarily be the one whose
    191  * declaring class is assignable from the reference type of the interface
    192  * that the proxy's method was invoked through.  This limitation exists
    193  * because the corresponding method implementation in the generated proxy
    194  * class cannot determine which interface it was invoked through.
    195  * Therefore, when a duplicate method is invoked on a proxy instance,
    196  * the {@code Method} object for the method in the foremost interface
    197  * that contains the method (either directly or inherited through a
    198  * superinterface) in the proxy class's list of interfaces is passed to
    199  * the invocation handler's {@code invoke} method, regardless of the
    200  * reference type through which the method invocation occurred.
    201  *
    202  * <p>If a proxy interface contains a method with the same name and
    203  * parameter signature as the {@code hashCode}, {@code equals},
    204  * or {@code toString} methods of {@code java.lang.Object},
    205  * when such a method is invoked on a proxy instance, the
    206  * {@code Method} object passed to the invocation handler will have
    207  * {@code java.lang.Object} as its declaring class.  In other words,
    208  * the public, non-final methods of {@code java.lang.Object}
    209  * logically precede all of the proxy interfaces for the determination of
    210  * which {@code Method} object to pass to the invocation handler.
    211  *
    212  * <p>Note also that when a duplicate method is dispatched to an
    213  * invocation handler, the {@code invoke} method may only throw
    214  * checked exception types that are assignable to one of the exception
    215  * types in the {@code throws} clause of the method in <i>all</i> of
    216  * the proxy interfaces that it can be invoked through.  If the
    217  * {@code invoke} method throws a checked exception that is not
    218  * assignable to any of the exception types declared by the method in one
    219  * of the proxy interfaces that it can be invoked through, then an
    220  * unchecked {@code UndeclaredThrowableException} will be thrown by
    221  * the invocation on the proxy instance.  This restriction means that not
    222  * all of the exception types returned by invoking
    223  * {@code getExceptionTypes} on the {@code Method} object
    224  * passed to the {@code invoke} method can necessarily be thrown
    225  * successfully by the {@code invoke} method.
    226  *
    227  * @author      Peter Jones
    228  * @see         InvocationHandler
    229  * @since       1.3
    230  */
    231 public class Proxy implements java.io.Serializable {
    232 
    233     private static final long serialVersionUID = -2222568056686623797L;
    234 
    235     /** prefix for all proxy class names */
    236     private final static String proxyClassNamePrefix = "$Proxy";
    237 
    238     /** parameter types of a proxy class constructor */
    239     private final static Class[] constructorParams =
    240         { InvocationHandler.class };
    241 
    242     /** maps a class loader to the proxy class cache for that loader */
    243     private static Map<ClassLoader, Map<List<String>, Object>> loaderToCache
    244         = new WeakHashMap<>();
    245 
    246     /** marks that a particular proxy class is currently being generated */
    247     private static Object pendingGenerationMarker = new Object();
    248 
    249     /** next number to use for generation of unique proxy class names */
    250     private static long nextUniqueNumber = 0;
    251     private static Object nextUniqueNumberLock = new Object();
    252 
    253     /** set of all generated proxy classes, for isProxyClass implementation */
    254     private static Map<Class<?>, Void> proxyClasses =
    255         Collections.synchronizedMap(new WeakHashMap<Class<?>, Void>());
    256 
    257     /**
    258      * the invocation handler for this proxy instance.
    259      * @serial
    260      */
    261     protected InvocationHandler h;
    262 
    263     /**
    264      * Orders methods by their name, parameters, return type and inheritance relationship.
    265      *
    266      * @hide
    267      */
    268     private static final Comparator<Method> ORDER_BY_SIGNATURE_AND_SUBTYPE = new Comparator<Method>() {
    269         @Override public int compare(Method a, Method b) {
    270             int comparison = Method.ORDER_BY_SIGNATURE.compare(a, b);
    271             if (comparison != 0) {
    272                 return comparison;
    273             }
    274             Class<?> aClass = a.getDeclaringClass();
    275             Class<?> bClass = b.getDeclaringClass();
    276             if (aClass == bClass) {
    277                 return 0;
    278             } else if (aClass.isAssignableFrom(bClass)) {
    279                 return 1;
    280             } else if (bClass.isAssignableFrom(aClass)) {
    281                 return -1;
    282             } else {
    283                 return 0;
    284             }
    285         }
    286     };
    287 
    288     /**
    289      * Prohibits instantiation.
    290      */
    291     private Proxy() {
    292     }
    293 
    294     /**
    295      * Constructs a new {@code Proxy} instance from a subclass
    296      * (typically, a dynamic proxy class) with the specified value
    297      * for its invocation handler.
    298      *
    299      * @param   h the invocation handler for this proxy instance
    300      */
    301     protected Proxy(InvocationHandler h) {
    302         this.h = h;
    303     }
    304 
    305     /**
    306      * Returns the {@code java.lang.Class} object for a proxy class
    307      * given a class loader and an array of interfaces.  The proxy class
    308      * will be defined by the specified class loader and will implement
    309      * all of the supplied interfaces.  If a proxy class for the same
    310      * permutation of interfaces has already been defined by the class
    311      * loader, then the existing proxy class will be returned; otherwise,
    312      * a proxy class for those interfaces will be generated dynamically
    313      * and defined by the class loader.
    314      *
    315      * <p>There are several restrictions on the parameters that may be
    316      * passed to {@code Proxy.getProxyClass}:
    317      *
    318      * <ul>
    319      * <li>All of the {@code Class} objects in the
    320      * {@code interfaces} array must represent interfaces, not
    321      * classes or primitive types.
    322      *
    323      * <li>No two elements in the {@code interfaces} array may
    324      * refer to identical {@code Class} objects.
    325      *
    326      * <li>All of the interface types must be visible by name through the
    327      * specified class loader.  In other words, for class loader
    328      * {@code cl} and every interface {@code i}, the following
    329      * expression must be true:
    330      * <pre>
    331      *     Class.forName(i.getName(), false, cl) == i
    332      * </pre>
    333      *
    334      * <li>All non-public interfaces must be in the same package;
    335      * otherwise, it would not be possible for the proxy class to
    336      * implement all of the interfaces, regardless of what package it is
    337      * defined in.
    338      *
    339      * <li>For any set of member methods of the specified interfaces
    340      * that have the same signature:
    341      * <ul>
    342      * <li>If the return type of any of the methods is a primitive
    343      * type or void, then all of the methods must have that same
    344      * return type.
    345      * <li>Otherwise, one of the methods must have a return type that
    346      * is assignable to all of the return types of the rest of the
    347      * methods.
    348      * </ul>
    349      *
    350      * <li>The resulting proxy class must not exceed any limits imposed
    351      * on classes by the virtual machine.  For example, the VM may limit
    352      * the number of interfaces that a class may implement to 65535; in
    353      * that case, the size of the {@code interfaces} array must not
    354      * exceed 65535.
    355      * </ul>
    356      *
    357      * <p>If any of these restrictions are violated,
    358      * {@code Proxy.getProxyClass} will throw an
    359      * {@code IllegalArgumentException}.  If the {@code interfaces}
    360      * array argument or any of its elements are {@code null}, a
    361      * {@code NullPointerException} will be thrown.
    362      *
    363      * <p>Note that the order of the specified proxy interfaces is
    364      * significant: two requests for a proxy class with the same combination
    365      * of interfaces but in a different order will result in two distinct
    366      * proxy classes.
    367      *
    368      * @param   loader the class loader to define the proxy class
    369      * @param   interfaces the list of interfaces for the proxy class
    370      *          to implement
    371      * @return  a proxy class that is defined in the specified class loader
    372      *          and that implements the specified interfaces
    373      * @throws  IllegalArgumentException if any of the restrictions on the
    374      *          parameters that may be passed to {@code getProxyClass}
    375      *          are violated
    376      * @throws  NullPointerException if the {@code interfaces} array
    377      *          argument or any of its elements are {@code null}
    378      */
    379     @CallerSensitive
    380     public static Class<?> getProxyClass(ClassLoader loader,
    381                                          Class<?>... interfaces)
    382         throws IllegalArgumentException
    383     {
    384         return getProxyClass0(loader, interfaces);
    385     }
    386 
    387     /**
    388      * Generate a proxy class.  Must call the checkProxyAccess method
    389      * to perform permission checks before calling this.
    390      */
    391     private static Class<?> getProxyClass0(ClassLoader loader,
    392                                            Class<?>... interfaces) {
    393         if (interfaces.length > 65535) {
    394             throw new IllegalArgumentException("interface limit exceeded");
    395         }
    396 
    397         Class<?> proxyClass = null;
    398 
    399         /* collect interface names to use as key for proxy class cache */
    400         String[] interfaceNames = new String[interfaces.length];
    401 
    402         // for detecting duplicates
    403         Set<Class<?>> interfaceSet = new HashSet<>();
    404 
    405         for (int i = 0; i < interfaces.length; i++) {
    406             /*
    407              * Verify that the class loader resolves the name of this
    408              * interface to the same Class object.
    409              */
    410             String interfaceName = interfaces[i].getName();
    411             Class<?> interfaceClass = null;
    412             try {
    413                 interfaceClass = Class.forName(interfaceName, false, loader);
    414             } catch (ClassNotFoundException e) {
    415             }
    416             if (interfaceClass != interfaces[i]) {
    417                 throw new IllegalArgumentException(
    418                     interfaces[i] + " is not visible from class loader");
    419             }
    420 
    421             /*
    422              * Verify that the Class object actually represents an
    423              * interface.
    424              */
    425             if (!interfaceClass.isInterface()) {
    426                 throw new IllegalArgumentException(
    427                     interfaceClass.getName() + " is not an interface");
    428             }
    429 
    430             /*
    431              * Verify that this interface is not a duplicate.
    432              */
    433             if (interfaceSet.contains(interfaceClass)) {
    434                 throw new IllegalArgumentException(
    435                     "repeated interface: " + interfaceClass.getName());
    436             }
    437             interfaceSet.add(interfaceClass);
    438 
    439             interfaceNames[i] = interfaceName;
    440         }
    441 
    442         /*
    443          * Using string representations of the proxy interfaces as
    444          * keys in the proxy class cache (instead of their Class
    445          * objects) is sufficient because we require the proxy
    446          * interfaces to be resolvable by name through the supplied
    447          * class loader, and it has the advantage that using a string
    448          * representation of a class makes for an implicit weak
    449          * reference to the class.
    450          */
    451         List<String> key = Arrays.asList(interfaceNames);
    452 
    453         /*
    454          * Find or create the proxy class cache for the class loader.
    455          */
    456         Map<List<String>, Object> cache;
    457         synchronized (loaderToCache) {
    458             cache = loaderToCache.get(loader);
    459             if (cache == null) {
    460                 cache = new HashMap<>();
    461                 loaderToCache.put(loader, cache);
    462             }
    463             /*
    464              * This mapping will remain valid for the duration of this
    465              * method, without further synchronization, because the mapping
    466              * will only be removed if the class loader becomes unreachable.
    467              */
    468         }
    469 
    470         /*
    471          * Look up the list of interfaces in the proxy class cache using
    472          * the key.  This lookup will result in one of three possible
    473          * kinds of values:
    474          *     null, if there is currently no proxy class for the list of
    475          *         interfaces in the class loader,
    476          *     the pendingGenerationMarker object, if a proxy class for the
    477          *         list of interfaces is currently being generated,
    478          *     or a weak reference to a Class object, if a proxy class for
    479          *         the list of interfaces has already been generated.
    480          */
    481         synchronized (cache) {
    482             /*
    483              * Note that we need not worry about reaping the cache for
    484              * entries with cleared weak references because if a proxy class
    485              * has been garbage collected, its class loader will have been
    486              * garbage collected as well, so the entire cache will be reaped
    487              * from the loaderToCache map.
    488              */
    489             do {
    490                 Object value = cache.get(key);
    491                 if (value instanceof Reference) {
    492                     proxyClass = (Class<?>) ((Reference) value).get();
    493                 }
    494                 if (proxyClass != null) {
    495                     // proxy class already generated: return it
    496                     return proxyClass;
    497                 } else if (value == pendingGenerationMarker) {
    498                     // proxy class being generated: wait for it
    499                     try {
    500                         cache.wait();
    501                     } catch (InterruptedException e) {
    502                         /*
    503                          * The class generation that we are waiting for should
    504                          * take a small, bounded time, so we can safely ignore
    505                          * thread interrupts here.
    506                          */
    507                     }
    508                     continue;
    509                 } else {
    510                     /*
    511                      * No proxy class for this list of interfaces has been
    512                      * generated or is being generated, so we will go and
    513                      * generate it now.  Mark it as pending generation.
    514                      */
    515                     cache.put(key, pendingGenerationMarker);
    516                     break;
    517                 }
    518             } while (true);
    519         }
    520 
    521         try {
    522             String proxyPkg = null;     // package to define proxy class in
    523 
    524             /*
    525              * Record the package of a non-public proxy interface so that the
    526              * proxy class will be defined in the same package.  Verify that
    527              * all non-public proxy interfaces are in the same package.
    528              */
    529             for (int i = 0; i < interfaces.length; i++) {
    530                 int flags = interfaces[i].getModifiers();
    531                 if (!Modifier.isPublic(flags)) {
    532                     String name = interfaces[i].getName();
    533                     int n = name.lastIndexOf('.');
    534                     String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
    535                     if (proxyPkg == null) {
    536                         proxyPkg = pkg;
    537                     } else if (!pkg.equals(proxyPkg)) {
    538                         throw new IllegalArgumentException(
    539                             "non-public interfaces from different packages");
    540                     }
    541                 }
    542             }
    543 
    544             if (proxyPkg == null) {
    545                 // if no non-public proxy interfaces, use the default package.
    546                 proxyPkg = "";
    547             }
    548 
    549             {
    550                 // Android-changed: Generate the proxy directly instead of calling
    551                 // through to ProxyGenerator.
    552                 List<Method> methods = getMethods(interfaces);
    553                 Collections.sort(methods, ORDER_BY_SIGNATURE_AND_SUBTYPE);
    554                 validateReturnTypes(methods);
    555                 List<Class<?>[]> exceptions = deduplicateAndGetExceptions(methods);
    556 
    557                 Method[] methodsArray = methods.toArray(new Method[methods.size()]);
    558                 Class<?>[][] exceptionsArray = exceptions.toArray(new Class<?>[exceptions.size()][]);
    559 
    560                 /*
    561                  * Choose a name for the proxy class to generate.
    562                  */
    563                 final long num;
    564                 synchronized (nextUniqueNumberLock) {
    565                     num = nextUniqueNumber++;
    566                 }
    567                 String proxyName = proxyPkg + proxyClassNamePrefix + num;
    568 
    569                 proxyClass = generateProxy(proxyName, interfaces, loader, methodsArray,
    570                         exceptionsArray);
    571             }
    572             // add to set of all generated proxy classes, for isProxyClass
    573             proxyClasses.put(proxyClass, null);
    574 
    575         } finally {
    576             /*
    577              * We must clean up the "pending generation" state of the proxy
    578              * class cache entry somehow.  If a proxy class was successfully
    579              * generated, store it in the cache (with a weak reference);
    580              * otherwise, remove the reserved entry.  In all cases, notify
    581              * all waiters on reserved entries in this cache.
    582              */
    583             synchronized (cache) {
    584                 if (proxyClass != null) {
    585                     cache.put(key, new WeakReference<Class<?>>(proxyClass));
    586                 } else {
    587                     cache.remove(key);
    588                 }
    589                 cache.notifyAll();
    590             }
    591         }
    592         return proxyClass;
    593     }
    594 
    595     /**
    596      * Remove methods that have the same name, parameters and return type. This
    597      * computes the exceptions of each method; this is the intersection of the
    598      * exceptions of equivalent methods.
    599      *
    600      * @param methods the methods to find exceptions for, ordered by name and
    601      *     signature.
    602      */
    603     private static List<Class<?>[]> deduplicateAndGetExceptions(List<Method> methods) {
    604         List<Class<?>[]> exceptions = new ArrayList<Class<?>[]>(methods.size());
    605 
    606         for (int i = 0; i < methods.size(); ) {
    607             Method method = methods.get(i);
    608             Class<?>[] exceptionTypes = method.getExceptionTypes();
    609 
    610             if (i > 0 && Method.ORDER_BY_SIGNATURE.compare(method, methods.get(i - 1)) == 0) {
    611                 exceptions.set(i - 1, intersectExceptions(exceptions.get(i - 1), exceptionTypes));
    612                 methods.remove(i);
    613             } else {
    614                 exceptions.add(exceptionTypes);
    615                 i++;
    616             }
    617         }
    618         return exceptions;
    619     }
    620 
    621     /**
    622      * Returns the exceptions that are declared in both {@code aExceptions} and
    623      * {@code bExceptions}. If an exception type in one array is a subtype of an
    624      * exception from the other, the subtype is included in the intersection.
    625      */
    626     private static Class<?>[] intersectExceptions(Class<?>[] aExceptions, Class<?>[] bExceptions) {
    627         if (aExceptions.length == 0 || bExceptions.length == 0) {
    628             return EmptyArray.CLASS;
    629         }
    630         if (Arrays.equals(aExceptions, bExceptions)) {
    631             return aExceptions;
    632         }
    633         Set<Class<?>> intersection = new HashSet<Class<?>>();
    634         for (Class<?> a : aExceptions) {
    635             for (Class<?> b : bExceptions) {
    636                 if (a.isAssignableFrom(b)) {
    637                     intersection.add(b);
    638                 } else if (b.isAssignableFrom(a)) {
    639                     intersection.add(a);
    640                 }
    641             }
    642         }
    643         return intersection.toArray(new Class<?>[intersection.size()]);
    644     }
    645 
    646 
    647     /**
    648      * Throws if any two methods in {@code methods} have the same name and
    649      * parameters but incompatible return types.
    650      *
    651      * @param methods the methods to find exceptions for, ordered by name and
    652      *     signature.
    653      */
    654     private static void validateReturnTypes(List<Method> methods) {
    655         Method vs = null;
    656         for (Method method : methods) {
    657             if (vs == null || !vs.equalNameAndParameters(method)) {
    658                 vs = method; // this has a different name or parameters
    659                 continue;
    660             }
    661             Class<?> returnType = method.getReturnType();
    662             Class<?> vsReturnType = vs.getReturnType();
    663             if (returnType.isInterface() && vsReturnType.isInterface()) {
    664                 // all interfaces are mutually compatible
    665             } else if (vsReturnType.isAssignableFrom(returnType)) {
    666                 vs = method; // the new return type is a subtype; use it instead
    667             } else if (!returnType.isAssignableFrom(vsReturnType)) {
    668                 throw new IllegalArgumentException("proxied interface methods have incompatible "
    669                         + "return types:\n  " + vs + "\n  " + method);
    670             }
    671         }
    672     }
    673 
    674     private static List<Method> getMethods(Class<?>[] interfaces) {
    675         List<Method> result = new ArrayList<Method>();
    676         try {
    677             result.add(Object.class.getMethod("equals", Object.class));
    678             result.add(Object.class.getMethod("hashCode", EmptyArray.CLASS));
    679             result.add(Object.class.getMethod("toString", EmptyArray.CLASS));
    680         } catch (NoSuchMethodException e) {
    681             throw new AssertionError();
    682         }
    683 
    684         getMethodsRecursive(interfaces, result);
    685         return result;
    686     }
    687 
    688     /**
    689      * Fills {@code proxiedMethods} with the methods of {@code interfaces} and
    690      * the interfaces they extend. May contain duplicates.
    691      */
    692     private static void getMethodsRecursive(Class<?>[] interfaces, List<Method> methods) {
    693         for (Class<?> i : interfaces) {
    694             getMethodsRecursive(i.getInterfaces(), methods);
    695             Collections.addAll(methods, i.getDeclaredMethods());
    696         }
    697     }
    698 
    699     /**
    700      * Returns an instance of a proxy class for the specified interfaces
    701      * that dispatches method invocations to the specified invocation
    702      * handler.  This method is equivalent to:
    703      * <pre>
    704      *     Proxy.getProxyClass(loader, interfaces).
    705      *         getConstructor(new Class[] { InvocationHandler.class }).
    706      *         newInstance(new Object[] { handler });
    707      * </pre>
    708      *
    709      * <p>{@code Proxy.newProxyInstance} throws
    710      * {@code IllegalArgumentException} for the same reasons that
    711      * {@code Proxy.getProxyClass} does.
    712      *
    713      * @param   loader the class loader to define the proxy class
    714      * @param   interfaces the list of interfaces for the proxy class
    715      *          to implement
    716      * @param   h the invocation handler to dispatch method invocations to
    717      * @return  a proxy instance with the specified invocation handler of a
    718      *          proxy class that is defined by the specified class loader
    719      *          and that implements the specified interfaces
    720      * @throws  IllegalArgumentException if any of the restrictions on the
    721      *          parameters that may be passed to {@code getProxyClass}
    722      *          are violated
    723      * @throws  NullPointerException if the {@code interfaces} array
    724      *          argument or any of its elements are {@code null}, or
    725      *          if the invocation handler, {@code h}, is
    726      *          {@code null}
    727      */
    728     @CallerSensitive
    729     public static Object newProxyInstance(ClassLoader loader,
    730                                           Class<?>[] interfaces,
    731                                           InvocationHandler h)
    732         throws IllegalArgumentException
    733     {
    734         if (h == null) {
    735             throw new NullPointerException();
    736         }
    737 
    738         /*
    739          * Look up or generate the designated proxy class.
    740          */
    741         Class<?> cl = getProxyClass0(loader, interfaces);
    742 
    743         /*
    744          * Invoke its constructor with the designated invocation handler.
    745          */
    746         try {
    747             final Constructor<?> cons = cl.getConstructor(constructorParams);
    748             return newInstance(cons, h);
    749         } catch (NoSuchMethodException e) {
    750             throw new InternalError(e.toString());
    751         }
    752     }
    753 
    754     private static Object newInstance(Constructor<?> cons, InvocationHandler h) {
    755         try {
    756             return cons.newInstance(new Object[] {h} );
    757         } catch (IllegalAccessException | InstantiationException e) {
    758             throw new InternalError(e.toString());
    759         } catch (InvocationTargetException e) {
    760             Throwable t = e.getCause();
    761             if (t instanceof RuntimeException) {
    762                 throw (RuntimeException) t;
    763             } else {
    764                 throw new InternalError(t.toString());
    765             }
    766         }
    767     }
    768 
    769     /**
    770      * Returns true if and only if the specified class was dynamically
    771      * generated to be a proxy class using the {@code getProxyClass}
    772      * method or the {@code newProxyInstance} method.
    773      *
    774      * <p>The reliability of this method is important for the ability
    775      * to use it to make security decisions, so its implementation should
    776      * not just test if the class in question extends {@code Proxy}.
    777      *
    778      * @param   cl the class to test
    779      * @return  {@code true} if the class is a proxy class and
    780      *          {@code false} otherwise
    781      * @throws  NullPointerException if {@code cl} is {@code null}
    782      */
    783     public static boolean isProxyClass(Class<?> cl) {
    784         if (cl == null) {
    785             throw new NullPointerException();
    786         }
    787 
    788         return proxyClasses.containsKey(cl);
    789     }
    790 
    791     /**
    792      * Returns the invocation handler for the specified proxy instance.
    793      *
    794      * @param   proxy the proxy instance to return the invocation handler for
    795      * @return  the invocation handler for the proxy instance
    796      * @throws  IllegalArgumentException if the argument is not a
    797      *          proxy instance
    798      */
    799     public static InvocationHandler getInvocationHandler(Object proxy)
    800         throws IllegalArgumentException
    801     {
    802         /*
    803          * Verify that the object is actually a proxy instance.
    804          */
    805         if (!(proxy instanceof Proxy)) {
    806             throw new IllegalArgumentException("not a proxy instance");
    807         }
    808         return ((Proxy) proxy).h;
    809     }
    810 
    811     private static Object invoke(Proxy proxy, Method method, Object[] args) throws Throwable {
    812         InvocationHandler h = proxy.h;
    813         return h.invoke(proxy, method, args);
    814     }
    815 
    816     private static native Class<?> generateProxy(String name, Class<?>[] interfaces,
    817                                                  ClassLoader loader, Method[] methods,
    818                                                  Class<?>[][] exceptions);
    819 
    820     // Temporary methods.
    821     private static void reserved1() {};
    822     private static void reserved2() {};
    823 }
    824