• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
Proxy()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      */
Proxy(InvocationHandler h)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
getProxyClass(ClassLoader loader, Class<?>... interfaces)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      */
getProxyClass0(ClassLoader loader, Class<?>... interfaces)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      */
deduplicateAndGetExceptions(List<Method> methods)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      */
intersectExceptions(Class<?>[] aExceptions, Class<?>[] bExceptions)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      */
validateReturnTypes(List<Method> methods)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 
getMethods(Class<?>[] interfaces)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      */
getMethodsRecursive(Class<?>[] interfaces, List<Method> methods)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
newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)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 
newInstance(Constructor<?> cons, InvocationHandler h)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      */
isProxyClass(Class<?> cl)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      */
getInvocationHandler(Object proxy)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 
invoke(Proxy proxy, Method method, Object[] args)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 
generateProxy(String name, Class<?>[] interfaces, ClassLoader loader, Method[] methods, Class<?>[][] exceptions)816     private static native Class<?> generateProxy(String name, Class<?>[] interfaces,
817                                                  ClassLoader loader, Method[] methods,
818                                                  Class<?>[][] exceptions);
819 
820     // Temporary methods.
reserved1()821     private static void reserved1() {};
reserved2()822     private static void reserved2() {};
823 }
824