1 /*
2  * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
3  * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
4  *
5  *
6  *
7  *
8  *
9  *
10  *
11  *
12  *
13  *
14  *
15  *
16  *
17  *
18  *
19  *
20  *
21  *
22  *
23  *
24  */

25
26 package java.lang.reflect;
27
28 import java.lang.ref.WeakReference;
29 import java.security.AccessController;
30 import java.security.PrivilegedAction;
31 import java.util.Arrays;
32 import java.util.IdentityHashMap;
33 import java.util.Map;
34 import java.util.Objects;
35 import java.util.concurrent.atomic.AtomicLong;
36 import java.util.function.BiFunction;
37 import sun.misc.ProxyGenerator;
38 import sun.misc.VM;
39 import sun.reflect.CallerSensitive;
40 import sun.reflect.Reflection;
41 import sun.reflect.misc.ReflectUtil;
42 import sun.security.util.SecurityConstants;
43
44 /**
45  * {@code Proxy} provides static methods for creating dynamic proxy
46  * classes and instances, and it is also the superclass of all
47  * dynamic proxy classes created by those methods.
48  *
49  * <p>To create a proxy for some interface {@code Foo}:
50  * <pre>
51  *     InvocationHandler handler = new MyInvocationHandler(...);
52  *     Class&lt;?&gt; proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), Foo.class);
53  *     Foo f = (Foo) proxyClass.getConstructor(InvocationHandler.class).
54  *                     newInstance(handler);
55  * </pre>
56  * or more simply:
57  * <pre>
58  *     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
59  *                                          new Class&lt;?&gt;[] { Foo.class },
60  *                                          handler);
61  * </pre>
62  *
63  * <p>A <i>dynamic proxy class</i> (simply referred to as a <i>proxy
64  * class</i> below) is a class that implements a list of interfaces
65  * specified at runtime when the class is created, with behavior as
66  * described below.
67  *
68  * A <i>proxy interface</i> is such an interface that is implemented
69  * by a proxy class.
70  *
71  * A <i>proxy instance</i> is an instance of a proxy class.
72  *
73  * Each proxy instance has an associated <i>invocation handler</i>
74  * object, which implements the interface {@link InvocationHandler}.
75  * A method invocation on a proxy instance through one of its proxy
76  * interfaces will be dispatched to the {@link InvocationHandler#invoke
77  * invoke} method of the instance's invocation handler, passing the proxy
78  * instance, a {@code java.lang.reflect.Method} object identifying
79  * the method that was invoked, and an array of type {@code Object}
80  * containing the arguments.  The invocation handler processes the
81  * encoded method invocation as appropriate and the result that it
82  * returns will be returned as the result of the method invocation on
83  * the proxy instance.
84  *
85  * <p>A proxy class has the following properties:
86  *
87  * <ul>
88  * <li>Proxy classes are <em>publicfinal, and not abstract</em> if
89  * all proxy interfaces are public.</li>
90  *
91  * <li>Proxy classes are <em>non-publicfinal, and not abstract</em> if
92  * any of the proxy interfaces is non-public.</li>
93  *
94  * <li>The unqualified name of a proxy class is unspecified.  The space
95  * of class names that begin with the string {@code "$Proxy"}
96  * should be, however, reserved for proxy classes.
97  *
98  * <li>A proxy class extends {@code java.lang.reflect.Proxy}.
99  *
100  * <li>A proxy class implements exactly the interfaces specified at its
101  * creation, in the same order.
102  *
103  * <li>If a proxy class implements a non-public interface, then it will
104  * be defined in the same package as that interface.  Otherwise, the
105  * package of a proxy class is also unspecified.  Note that package
106  * sealing will not prevent a proxy class from being successfully defined
107  * in a particular package at runtime, and neither will classes already
108  * defined by the same class loader and the same package with particular
109  * signers.
110  *
111  * <li>Since a proxy class implements all of the interfaces specified at
112  * its creation, invoking {@code getInterfaces} on its
113  * {@code Class} object will return an array containing the same
114  * list of interfaces (in the order specified at its creation), invoking
115  * {@code getMethods} on its {@code Class} object will return
116  * an array of {@code Method} objects that include all of the
117  * methods in those interfaces, and invoking {@code getMethod} will
118  * find methods in the proxy interfaces as would be expected.
119  *
120  * <li>The {@link Proxy#isProxyClass Proxy.isProxyClass} method will
121  * return true if it is passed a proxy class-- a class returned by
122  * {@code Proxy.getProxyClass} or the class of an object returned by
123  * {@code Proxy.newProxyInstance}-- and false otherwise.
124  *
125  * <li>The {@code java.security.ProtectionDomain} of a proxy class
126  * is the same as that of system classes loaded by the bootstrap class
127  * loader, such as {@code java.lang.Object}, because the code for a
128  * proxy class is generated by trusted system code.  This protection
129  * domain will typically be granted
130  * {@code java.security.AllPermission}.
131  *
132  * <li>Each proxy class has one public constructor that takes one argument,
133  * an implementation of the interface {@link InvocationHandler}, to set
134  * the invocation handler for a proxy instance.  Rather than having to use
135  * the reflection API to access the public constructor, a proxy instance
136  * can be also be created by calling the {@link Proxy#newProxyInstance
137  * Proxy.newProxyInstance} method, which combines the actions of calling
138  * {@link Proxy#getProxyClass Proxy.getProxyClass} with invoking the
139  * constructor with an invocation handler.
140  * </ul>
141  *
142  * <p>A proxy instance has the following properties:
143  *
144  * <ul>
145  * <li>Given a proxy instance {@code proxy} and one of the
146  * interfaces implemented by its proxy class {@code Foo}, the
147  * following expression will return true:
148  * <pre>
149  *     {@code proxy instanceof Foo}
150  * </pre>
151  * and the following cast operation will succeed (rather than throwing
152  * a {@code ClassCastException}):
153  * <pre>
154  *     {@code (Foo) proxy}
155  * </pre>
156  *
157  * <li>Each proxy instance has an associated invocation handler, the one
158  * that was passed to its constructor.  The static
159  * {@link Proxy#getInvocationHandler Proxy.getInvocationHandler} method
160  * will return the invocation handler associated with the proxy instance
161  * passed as its argument.
162  *
163  * <li>An interface method invocation on a proxy instance will be
164  * encoded and dispatched to the invocation handler's {@link
165  * InvocationHandler#invoke invoke} method as described in the
166  * documentation for that method.
167  *
168  * <li>An invocation of the {@code hashCode},
169  * {@code equals}, or {@code toString} methods declared in
170  * {@code java.lang.Object} on a proxy instance will be encoded and
171  * dispatched to the invocation handler's {@code invoke} method in
172  * the same manner as interface method invocations are encoded and
173  * dispatched, as described above.  The declaring class of the
174  * {@code Method} object passed to {@code invoke} will be
175  * {@code java.lang.Object}.  Other public methods of a proxy
176  * instance inherited from {@code java.lang.Object} are not
177  * overridden by a proxy class, so invocations of those methods behave
178  * like they do for instances of {@code java.lang.Object}.
179  * </ul>
180  *
181  * <h3>Methods Duplicated in Multiple Proxy Interfaces</h3>
182  *
183  * <p>When two or more interfaces of a proxy class contain a method with
184  * the same name and parameter signature, the order of the proxy class's
185  * interfaces becomes significant.  When such a <i>duplicate method</i>
186  * is invoked on a proxy instance, the {@code Method} object passed
187  * to the invocation handler will not necessarily be the one whose
188  * declaring class is assignable from the reference type of the interface
189  * that the proxy's method was invoked through.  This limitation exists
190  * because the corresponding method implementation in the generated proxy
191  * class cannot determine which interface it was invoked through.
192  * Therefore, when a duplicate method is invoked on a proxy instance,
193  * the {@code Method} object for the method in the foremost interface
194  * that contains the method (either directly or inherited through a
195  * superinterface) in the proxy class's list of interfaces is passed to
196  * the invocation handler's {@code invoke} method, regardless of the
197  * reference type through which the method invocation occurred.
198  *
199  * <p>If a proxy interface contains a method with the same name and
200  * parameter signature as the {@code hashCode}, {@code equals},
201  * or {@code toString} methods of {@code java.lang.Object},
202  * when such a method is invoked on a proxy instance, the
203  * {@code Method} object passed to the invocation handler will have
204  * {@code java.lang.Object} as its declaring class.  In other words,
205  * the public, non-final methods of {@code java.lang.Object}
206  * logically precede all of the proxy interfaces for the determination of
207  * which {@code Method} object to pass to the invocation handler.
208  *
209  * <p>Note also that when a duplicate method is dispatched to an
210  * invocation handler, the {@code invoke} method may only throw
211  * checked exception types that are assignable to one of the exception
212  * types in the {@code throws} clause of the method in <i>all</i> of
213  * the proxy interfaces that it can be invoked through.  If the
214  * {@code invoke} method throws a checked exception that is not
215  * assignable to any of the exception types declared by the method in one
216  * of the proxy interfaces that it can be invoked through, then an
217  * unchecked {@code UndeclaredThrowableException} will be thrown by
218  * the invocation on the proxy instance.  This restriction means that not
219  * all of the exception types returned by invoking
220  * {@code getExceptionTypes} on the {@code Method} object
221  * passed to the {@code invoke} method can necessarily be thrown
222  * successfully by the {@code invoke} method.
223  *
224  * @author      Peter Jones
225  * @see         InvocationHandler
226  * @since       1.3
227  */

228 public class Proxy implements java.io.Serializable {
229
230     private static final long serialVersionUID = -2222568056686623797L;
231
232     /** parameter types of a proxy class constructor */
233     private static final Class<?>[] constructorParams =
234         { InvocationHandler.class };
235
236     /**
237      * a cache of proxy classes
238      */

239     private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
240         proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
241
242     /**
243      * the invocation handler for this proxy instance.
244      * @serial
245      */

246     protected InvocationHandler h;
247
248     /**
249      * Prohibits instantiation.
250      */

251     private Proxy() {
252     }
253
254     /**
255      * Constructs a new {@code Proxy} instance from a subclass
256      * (typically, a dynamic proxy class) with the specified value
257      * for its invocation handler.
258      *
259      * @param  h the invocation handler for this proxy instance
260      *
261      * @throws NullPointerException if the given invocation handler, {@code h},
262      *         is {@code null}.
263      */

264     protected Proxy(InvocationHandler h) {
265         Objects.requireNonNull(h);
266         this.h = h;
267     }
268
269     /**
270      * Returns the {@code java.lang.Class} object for a proxy class
271      * given a class loader and an array of interfaces.  The proxy class
272      * will be defined by the specified class loader and will implement
273      * all of the supplied interfaces.  If any of the given interfaces
274      * is non-public, the proxy class will be non-public. If a proxy class
275      * for the same permutation of interfaces has already been defined by the
276      * class loader, then the existing proxy class will be returned; otherwise,
277      * a proxy class for those interfaces will be generated dynamically
278      * and defined by the class loader.
279      *
280      * <p>There are several restrictions on the parameters that may be
281      * passed to {@code Proxy.getProxyClass}:
282      *
283      * <ul>
284      * <li>All of the {@code Class} objects in the
285      * {@code interfaces} array must represent interfaces, not
286      * classes or primitive types.
287      *
288      * <li>No two elements in the {@code interfaces} array may
289      * refer to identical {@code Class} objects.
290      *
291      * <li>All of the interface types must be visible by name through the
292      * specified class loader.  In other words, for class loader
293      * {@code cl} and every interface {@code i}, the following
294      * expression must be true:
295      * <pre>
296      *     Class.forName(i.getName(), false, cl) == i
297      * </pre>
298      *
299      * <li>All non-public interfaces must be in the same package;
300      * otherwise, it would not be possible for the proxy class to
301      * implement all of the interfaces, regardless of what package it is
302      * defined in.
303      *
304      * <li>For any set of member methods of the specified interfaces
305      * that have the same signature:
306      * <ul>
307      * <li>If the return type of any of the methods is a primitive
308      * type or void, then all of the methods must have that same
309      * return type.
310      * <li>Otherwise, one of the methods must have a return type that
311      * is assignable to all of the return types of the rest of the
312      * methods.
313      * </ul>
314      *
315      * <li>The resulting proxy class must not exceed any limits imposed
316      * on classes by the virtual machine.  For example, the VM may limit
317      * the number of interfaces that a class may implement to 65535; in
318      * that case, the size of the {@code interfaces} array must not
319      * exceed 65535.
320      * </ul>
321      *
322      * <p>If any of these restrictions are violated,
323      * {@code Proxy.getProxyClass} will throw an
324      * {@code IllegalArgumentException}.  If the {@code interfaces}
325      * array argument or any of its elements are {@code null}, a
326      * {@code NullPointerException} will be thrown.
327      *
328      * <p>Note that the order of the specified proxy interfaces is
329      * significant: two requests for a proxy class with the same combination
330      * of interfaces but in a different order will result in two distinct
331      * proxy classes.
332      *
333      * @param   loader the class loader to define the proxy class
334      * @param   interfaces the list of interfaces for the proxy class
335      *          to implement
336      * @return  a proxy class that is defined in the specified class loader
337      *          and that implements the specified interfaces
338      * @throws  IllegalArgumentException if any of the restrictions on the
339      *          parameters that may be passed to {@code getProxyClass}
340      *          are violated
341      * @throws  SecurityException if a security manager, <em>s</em>, is present
342      *          and any of the following conditions is met:
343      *          <ul>
344      *             <li> the given {@code loader} is {@code null} and
345      *             the caller's class loader is not {@code null} and the
346      *             invocation of {@link SecurityManager#checkPermission
347      *             s.checkPermission} with
348      *             {@code RuntimePermission("getClassLoader")} permission
349      *             denies access.</li>
350      *             <li> for each proxy interface, {@code intf},
351      *             the caller's class loader is not the same as or an
352      *             ancestor of the class loader for {@code intf} and
353      *             invocation of {@link SecurityManager#checkPackageAccess
354      *             s.checkPackageAccess()} denies access to {@code intf}.</li>
355      *          </ul>
356
357      * @throws  NullPointerException if the {@code interfaces} array
358      *          argument or any of its elements are {@code null}
359      */

360     @CallerSensitive
361     public static Class<?> getProxyClass(ClassLoader loader,
362                                          Class<?>... interfaces)
363         throws IllegalArgumentException
364     {
365         final Class<?>[] intfs = interfaces.clone();
366         final SecurityManager sm = System.getSecurityManager();
367         if (sm != null) {
368             checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
369         }
370
371         return getProxyClass0(loader, intfs);
372     }
373
374     /*
375      * Check permissions required to create a Proxy class.
376      *
377      * To define a proxy class, it performs the access checks as in
378      * Class.forName (VM will invoke ClassLoader.checkPackageAccess):
379      * 1. "getClassLoader" permission check if loader == null
380      * 2. checkPackageAccess on the interfaces it implements
381      *
382      * To get a constructor and new instance of a proxy class, it performs
383      * the package access check on the interfaces it implements
384      * as in Class.getConstructor.
385      *
386      * If an interface is non-public, the proxy class must be defined by
387      * the defining loader of the interface.  If the caller's class loader
388      * is not the same as the defining loader of the interface, the VM
389      * will throw IllegalAccessError when the generated proxy class is
390      * being defined via the defineClass0 method.
391      */

392     private static void checkProxyAccess(Class<?> caller,
393                                          ClassLoader loader,
394                                          Class<?>... interfaces)
395     {
396         SecurityManager sm = System.getSecurityManager();
397         if (sm != null) {
398             ClassLoader ccl = caller.getClassLoader();
399             if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {
400                 sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
401             }
402             ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
403         }
404     }
405
406     /**
407      * Generate a proxy class.  Must call the checkProxyAccess method
408      * to perform permission checks before calling this.
409      */

410     private static Class<?> getProxyClass0(ClassLoader loader,
411                                            Class<?>... interfaces) {
412         if (interfaces.length > 65535) {
413             throw new IllegalArgumentException("interface limit exceeded");
414         }
415
416         // If the proxy class defined by the given loader implementing
417         // the given interfaces exists, this will simply return the cached copy;
418         // otherwise, it will create the proxy class via the ProxyClassFactory
419         return proxyClassCache.get(loader, interfaces);
420     }
421
422     /*
423      * a key used for proxy class with 0 implemented interfaces
424      */

425     private static final Object key0 = new Object();
426
427     /*
428      * Key1 and Key2 are optimized for the common use of dynamic proxies
429      * that implement 1 or 2 interfaces.
430      */

431
432     /*
433      * a key used for proxy class with 1 implemented interface
434      */

435     private static final class Key1 extends WeakReference<Class<?>> {
436         private final int hash;
437
438         Key1(Class<?> intf) {
439             super(intf);
440             this.hash = intf.hashCode();
441         }
442
443         @Override
444         public int hashCode() {
445             return hash;
446         }
447
448         @Override
449         public boolean equals(Object obj) {
450             Class<?> intf;
451             return this == obj ||
452                    obj != null &&
453                    obj.getClass() == Key1.class &&
454                    (intf = get()) != null &&
455                    intf == ((Key1) obj).get();
456         }
457     }
458
459     /*
460      * a key used for proxy class with 2 implemented interfaces
461      */

462     private static final class Key2 extends WeakReference<Class<?>> {
463         private final int hash;
464         private final WeakReference<Class<?>> ref2;
465
466         Key2(Class<?> intf1, Class<?> intf2) {
467             super(intf1);
468             hash = 31 * intf1.hashCode() + intf2.hashCode();
469             ref2 = new WeakReference<Class<?>>(intf2);
470         }
471
472         @Override
473         public int hashCode() {
474             return hash;
475         }
476
477         @Override
478         public boolean equals(Object obj) {
479             Class<?> intf1, intf2;
480             return this == obj ||
481                    obj != null &&
482                    obj.getClass() == Key2.class &&
483                    (intf1 = get()) != null &&
484                    intf1 == ((Key2) obj).get() &&
485                    (intf2 = ref2.get()) != null &&
486                    intf2 == ((Key2) obj).ref2.get();
487         }
488     }
489
490     /*
491      * a key used for proxy class with any number of implemented interfaces
492      * (used here for 3 or more only)
493      */

494     private static final class KeyX {
495         private final int hash;
496         private final WeakReference<Class<?>>[] refs;
497
498         @SuppressWarnings("unchecked")
499         KeyX(Class<?>[] interfaces) {
500             hash = Arrays.hashCode(interfaces);
501             refs = (WeakReference<Class<?>>[])new WeakReference<?>[interfaces.length];
502             for (int i = 0; i < interfaces.length; i++) {
503                 refs[i] = new WeakReference<>(interfaces[i]);
504             }
505         }
506
507         @Override
508         public int hashCode() {
509             return hash;
510         }
511
512         @Override
513         public boolean equals(Object obj) {
514             return this == obj ||
515                    obj != null &&
516                    obj.getClass() == KeyX.class &&
517                    equals(refs, ((KeyX) obj).refs);
518         }
519
520         private static boolean equals(WeakReference<Class<?>>[] refs1,
521                                       WeakReference<Class<?>>[] refs2) {
522             if (refs1.length != refs2.length) {
523                 return false;
524             }
525             for (int i = 0; i < refs1.length; i++) {
526                 Class<?> intf = refs1[i].get();
527                 if (intf == null || intf != refs2[i].get()) {
528                     return false;
529                 }
530             }
531             return true;
532         }
533     }
534
535     /**
536      * A function that maps an array of interfaces to an optimal key where
537      * Class objects representing interfaces are weakly referenced.
538      */

539     private static final class KeyFactory
540         implements BiFunction<ClassLoader, Class<?>[], Object>
541     {
542         @Override
543         public Object apply(ClassLoader classLoader, Class<?>[] interfaces) {
544             switch (interfaces.length) {
545                 case 1: return new Key1(interfaces[0]); // the most frequent
546                 case 2: return new Key2(interfaces[0], interfaces[1]);
547                 case 0: return key0;
548                 defaultreturn new KeyX(interfaces);
549             }
550         }
551     }
552
553     /**
554      * A factory function that generates, defines and returns the proxy class given
555      * the ClassLoader and array of interfaces.
556      */

557     private static final class ProxyClassFactory
558         implements BiFunction<ClassLoader, Class<?>[], Class<?>>
559     {
560         // prefix for all proxy class names
561         private static final String proxyClassNamePrefix = "$Proxy";
562
563         // next number to use for generation of unique proxy class names
564         private static final AtomicLong nextUniqueNumber = new AtomicLong();
565
566         @Override
567         public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
568
569             Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
570             for (Class<?> intf : interfaces) {
571                 /*
572                  * Verify that the class loader resolves the name of this
573                  * interface to the same Class object.
574                  */

575                 Class<?> interfaceClass = null;
576                 try {
577                     interfaceClass = Class.forName(intf.getName(), false, loader);
578                 } catch (ClassNotFoundException e) {
579                 }
580                 if (interfaceClass != intf) {
581                     throw new IllegalArgumentException(
582                         intf + " is not visible from class loader");
583                 }
584                 /*
585                  * Verify that the Class object actually represents an
586                  * interface.
587                  */

588                 if (!interfaceClass.isInterface()) {
589                     throw new IllegalArgumentException(
590                         interfaceClass.getName() + " is not an interface");
591                 }
592                 /*
593                  * Verify that this interface is not a duplicate.
594                  */

595                 if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
596                     throw new IllegalArgumentException(
597                         "repeated interface: " + interfaceClass.getName());
598                 }
599             }
600
601             String proxyPkg = null;     // package to define proxy class in
602             int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
603
604             /*
605              * Record the package of a non-public proxy interface so that the
606              * proxy class will be defined in the same package.  Verify that
607              * all non-public proxy interfaces are in the same package.
608              */

609             for (Class<?> intf : interfaces) {
610                 int flags = intf.getModifiers();
611                 if (!Modifier.isPublic(flags)) {
612                     accessFlags = Modifier.FINAL;
613                     String name = intf.getName();
614                     int n = name.lastIndexOf('.');
615                     String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
616                     if (proxyPkg == null) {
617                         proxyPkg = pkg;
618                     } else if (!pkg.equals(proxyPkg)) {
619                         throw new IllegalArgumentException(
620                             "non-public interfaces from different packages");
621                     }
622                 }
623             }
624
625             if (proxyPkg == null) {
626                 // if no non-public proxy interfaces, use com.sun.proxy package
627                 proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
628             }
629
630             /*
631              * Choose a name for the proxy class to generate.
632              */

633             long num = nextUniqueNumber.getAndIncrement();
634             String proxyName = proxyPkg + proxyClassNamePrefix + num;
635
636             /*
637              * Generate the specified proxy class.
638              */

639             byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
640                 proxyName, interfaces, accessFlags);
641             try {
642                 return defineClass0(loader, proxyName,
643                                     proxyClassFile, 0, proxyClassFile.length);
644             } catch (ClassFormatError e) {
645                 /*
646                  * A ClassFormatError here means that (barring bugs in the
647                  * proxy class generation code) there was some other
648                  * invalid aspect of the arguments supplied to the proxy
649                  * class creation (such as virtual machine limitations
650                  * exceeded).
651                  */

652                 throw new IllegalArgumentException(e.toString());
653             }
654         }
655     }
656
657     /**
658      * Returns an instance of a proxy class for the specified interfaces
659      * that dispatches method invocations to the specified invocation
660      * handler.
661      *
662      * <p>{@code Proxy.newProxyInstance} throws
663      * {@code IllegalArgumentException} for the same reasons that
664      * {@code Proxy.getProxyClass} does.
665      *
666      * @param   loader the class loader to define the proxy class
667      * @param   interfaces the list of interfaces for the proxy class
668      *          to implement
669      * @param   h the invocation handler to dispatch method invocations to
670      * @return  a proxy instance with the specified invocation handler of a
671      *          proxy class that is defined by the specified class loader
672      *          and that implements the specified interfaces
673      * @throws  IllegalArgumentException if any of the restrictions on the
674      *          parameters that may be passed to {@code getProxyClass}
675      *          are violated
676      * @throws  SecurityException if a security manager, <em>s</em>, is present
677      *          and any of the following conditions is met:
678      *          <ul>
679      *          <li> the given {@code loader} is {@code null} and
680      *               the caller's class loader is not {@code null} and the
681      *               invocation of {@link SecurityManager#checkPermission
682      *               s.checkPermission} with
683      *               {@code RuntimePermission("getClassLoader")} permission
684      *               denies access;</li>
685      *          <li> for each proxy interface, {@code intf},
686      *               the caller's class loader is not the same as or an
687      *               ancestor of the class loader for {@code intf} and
688      *               invocation of {@link SecurityManager#checkPackageAccess
689      *               s.checkPackageAccess()} denies access to {@code intf};</li>
690      *          <li> any of the given proxy interfaces is non-public and the
691      *               caller class is not in the same {@linkplain Package runtime package}
692      *               as the non-public interface and the invocation of
693      *               {@link SecurityManager#checkPermission s.checkPermission} with
694      *               {@code ReflectPermission("newProxyInPackage.{package name}")}
695      *               permission denies access.</li>
696      *          </ul>
697      * @throws  NullPointerException if the {@code interfaces} array
698      *          argument or any of its elements are {@code null}, or
699      *          if the invocation handler, {@code h}, is
700      *          {@code null}
701      */

702     @CallerSensitive
703     public static Object newProxyInstance(ClassLoader loader,
704                                           Class<?>[] interfaces,
705                                           InvocationHandler h)
706         throws IllegalArgumentException
707     {
708         Objects.requireNonNull(h);
709
710         final Class<?>[] intfs = interfaces.clone();
711         final SecurityManager sm = System.getSecurityManager();
712         if (sm != null) {
713             checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
714         }
715
716         /*
717          * Look up or generate the designated proxy class.
718          */

719         Class<?> cl = getProxyClass0(loader, intfs);
720
721         /*
722          * Invoke its constructor with the designated invocation handler.
723          */

724         try {
725             if (sm != null) {
726                 checkNewProxyPermission(Reflection.getCallerClass(), cl);
727             }
728
729             final Constructor<?> cons = cl.getConstructor(constructorParams);
730             final InvocationHandler ih = h;
731             if (!Modifier.isPublic(cl.getModifiers())) {
732                 AccessController.doPrivileged(new PrivilegedAction<Void>() {
733                     public Void run() {
734                         cons.setAccessible(true);
735                         return null;
736                     }
737                 });
738             }
739             return cons.newInstance(new Object[]{h});
740         } catch (IllegalAccessException|InstantiationException e) {
741             throw new InternalError(e.toString(), e);
742         } catch (InvocationTargetException e) {
743             Throwable t = e.getCause();
744             if (t instanceof RuntimeException) {
745                 throw (RuntimeException) t;
746             } else {
747                 throw new InternalError(t.toString(), t);
748             }
749         } catch (NoSuchMethodException e) {
750             throw new InternalError(e.toString(), e);
751         }
752     }
753
754     private static void checkNewProxyPermission(Class<?> caller, Class<?> proxyClass) {
755         SecurityManager sm = System.getSecurityManager();
756         if (sm != null) {
757             if (ReflectUtil.isNonPublicProxyClass(proxyClass)) {
758                 ClassLoader ccl = caller.getClassLoader();
759                 ClassLoader pcl = proxyClass.getClassLoader();
760
761                 // do permission check if the caller is in a different runtime package
762                 // of the proxy class
763                 int n = proxyClass.getName().lastIndexOf('.');
764                 String pkg = (n == -1) ? "" : proxyClass.getName().substring(0, n);
765
766                 n = caller.getName().lastIndexOf('.');
767                 String callerPkg = (n == -1) ? "" : caller.getName().substring(0, n);
768
769                 if (pcl != ccl || !pkg.equals(callerPkg)) {
770                     sm.checkPermission(new ReflectPermission("newProxyInPackage." + pkg));
771                 }
772             }
773         }
774     }
775
776     /**
777      * Returns true if and only if the specified class was dynamically
778      * generated to be a proxy class using the {@code getProxyClass}
779      * method or the {@code newProxyInstance} method.
780      *
781      * <p>The reliability of this method is important for the ability
782      * to use it to make security decisions, so its implementation should
783      * not just test if the class in question extends {@code Proxy}.
784      *
785      * @param   cl the class to test
786      * @return  {@code trueif the class is a proxy class and
787      *          {@code false} otherwise
788      * @throws  NullPointerException if {@code cl} is {@code null}
789      */

790     public static boolean isProxyClass(Class<?> cl) {
791         return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);
792     }
793
794     /**
795      * Returns the invocation handler for the specified proxy instance.
796      *
797      * @param   proxy the proxy instance to return the invocation handler for
798      * @return  the invocation handler for the proxy instance
799      * @throws  IllegalArgumentException if the argument is not a
800      *          proxy instance
801      * @throws  SecurityException if a security manager, <em>s</em>, is present
802      *          and the caller's class loader is not the same as or an
803      *          ancestor of the class loader for the invocation handler
804      *          and invocation of {@link SecurityManager#checkPackageAccess
805      *          s.checkPackageAccess()} denies access to the invocation
806      *          handler's class.
807      */

808     @CallerSensitive
809     public static InvocationHandler getInvocationHandler(Object proxy)
810         throws IllegalArgumentException
811     {
812         /*
813          * Verify that the object is actually a proxy instance.
814          */

815         if (!isProxyClass(proxy.getClass())) {
816             throw new IllegalArgumentException("not a proxy instance");
817         }
818
819         final Proxy p = (Proxy) proxy;
820         final InvocationHandler ih = p.h;
821         if (System.getSecurityManager() != null) {
822             Class<?> ihClass = ih.getClass();
823             Class<?> caller = Reflection.getCallerClass();
824             if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(),
825                                                     ihClass.getClassLoader()))
826             {
827                 ReflectUtil.checkPackageAccess(ihClass);
828             }
829         }
830
831         return ih;
832     }
833
834     private static native Class<?> defineClass0(ClassLoader loader, String name,
835                                                 byte[] b, int off, int len);
836 }
837
Powered by JavaMelody