src/share/classes/java/lang/reflect/Proxy.java

Print this page




   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.reflect;
  27 
  28 import java.lang.ref.Reference;
  29 import java.lang.ref.WeakReference;
  30 import java.security.AccessController;
  31 import java.security.PrivilegedAction;
  32 import java.util.Arrays;
  33 import java.util.Collections;
  34 import java.util.HashMap;
  35 import java.util.HashSet;
  36 import java.util.Map;
  37 import java.util.Set;
  38 import java.util.List;
  39 import java.util.WeakHashMap;
  40 import sun.misc.ProxyGenerator;
  41 import sun.misc.VM;
  42 import sun.reflect.CallerSensitive;
  43 import sun.reflect.Reflection;
  44 import sun.reflect.misc.ReflectUtil;
  45 import sun.security.util.SecurityConstants;
  46 
  47 /**
  48  * {@code Proxy} provides static methods for creating dynamic proxy
  49  * classes and instances, and it is also the superclass of all
  50  * dynamic proxy classes created by those methods.
  51  *
  52  * <p>To create a proxy for some interface {@code Foo}:
  53  * <pre>
  54  *     InvocationHandler handler = new MyInvocationHandler(...);
  55  *     Class&lt;?&gt; proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), Foo.class);
  56  *     Foo f = (Foo) proxyClass.getConstructor(InvocationHandler.class).
  57  *                     newInstance(handler);
  58  * </pre>
  59  * or more simply:


 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      * Prohibits instantiation.
 265      */
 266     private Proxy() {
 267     }
 268 
 269     /**
 270      * Constructs a new {@code Proxy} instance from a subclass
 271      * (typically, a dynamic proxy class) with the specified value
 272      * for its invocation handler.
 273      *
 274      * @param   h the invocation handler for this proxy instance
 275      */


 406         SecurityManager sm = System.getSecurityManager();
 407         if (sm != null) {
 408             ClassLoader ccl = caller.getClassLoader();
 409             if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {
 410                 sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
 411             }
 412             ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
 413         }
 414     }
 415 
 416     /**
 417      * Generate a proxy class.  Must call the checkProxyAccess method
 418      * to perform permission checks before calling this.
 419      */
 420     private static Class<?> getProxyClass0(ClassLoader loader,
 421                                            Class<?>... interfaces) {
 422         if (interfaces.length > 65535) {
 423             throw new IllegalArgumentException("interface limit exceeded");
 424         }
 425 
 426         Class<?> proxyClass = null;




 427 
 428         /* collect interface names to use as key for proxy class cache */
 429         String[] interfaceNames = new String[interfaces.length];


 430 
 431         // for detecting duplicates
 432         Set<Class<?>> interfaceSet = new HashSet<>();


 433 
 434         for (int i = 0; i < interfaces.length; i++) {
 435             /*
 436              * Verify that the class loader resolves the name of this
 437              * interface to the same Class object.
 438              */
 439             String interfaceName = interfaces[i].getName();
 440             Class<?> interfaceClass = null;
 441             try {
 442                 interfaceClass = Class.forName(interfaceName, false, loader);
 443             } catch (ClassNotFoundException e) {

 444             }
 445             if (interfaceClass != interfaces[i]) {
 446                 throw new IllegalArgumentException(
 447                     interfaces[i] + " is not visible from class loader");

 448             }
 449 
 450             /*
 451              * Verify that the Class object actually represents an
 452              * interface.
 453              */
 454             if (!interfaceClass.isInterface()) {
 455                 throw new IllegalArgumentException(
 456                     interfaceClass.getName() + " is not an interface");


 457             }
 458 
 459             /*
 460              * Verify that this interface is not a duplicate.
 461              */
 462             if (interfaceSet.contains(interfaceClass)) {
 463                 throw new IllegalArgumentException(
 464                     "repeated interface: " + interfaceClass.getName());





 465             }
 466             interfaceSet.add(interfaceClass);
 467 
 468             interfaceNames[i] = interfaceName;


 469         }
 470 
 471         /*
 472          * Using string representations of the proxy interfaces as
 473          * keys in the proxy class cache (instead of their Class
 474          * objects) is sufficient because we require the proxy
 475          * interfaces to be resolvable by name through the supplied
 476          * class loader, and it has the advantage that using a string
 477          * representation of a class makes for an implicit weak
 478          * reference to the class.
 479          */
 480         List<String> key = Arrays.asList(interfaceNames);


 481 
 482         /*
 483          * Find or create the proxy class cache for the class loader.

 484          */
 485         Map<List<String>, Object> cache;
 486         synchronized (loaderToCache) {
 487             cache = loaderToCache.get(loader);
 488             if (cache == null) {
 489                 cache = new HashMap<>();
 490                 loaderToCache.put(loader, cache);



 491             }
 492             /*
 493              * This mapping will remain valid for the duration of this
 494              * method, without further synchronization, because the mapping
 495              * will only be removed if the class loader becomes unreachable.





























 496              */












 497         }
 498 
 499         /*
 500          * Look up the list of interfaces in the proxy class cache using
 501          * the key.  This lookup will result in one of three possible
 502          * kinds of values:
 503          *     null, if there is currently no proxy class for the list of
 504          *         interfaces in the class loader,
 505          *     the pendingGenerationMarker object, if a proxy class for the
 506          *         list of interfaces is currently being generated,
 507          *     or a weak reference to a Class object, if a proxy class for
 508          *         the list of interfaces has already been generated.
 509          */
 510         synchronized (cache) {













 511             /*
 512              * Note that we need not worry about reaping the cache for
 513              * entries with cleared weak references because if a proxy class
 514              * has been garbage collected, its class loader will have been
 515              * garbage collected as well, so the entire cache will be reaped
 516              * from the loaderToCache map.
 517              */
 518             do {
 519                 Object value = cache.get(key);
 520                 if (value instanceof Reference) {
 521                     proxyClass = (Class<?>) ((Reference) value).get();
 522                 }
 523                 if (proxyClass != null) {
 524                     // proxy class already generated: return it
 525                     return proxyClass;
 526                 } else if (value == pendingGenerationMarker) {
 527                     // proxy class being generated: wait for it
 528                     try {
 529                         cache.wait();
 530                     } catch (InterruptedException e) {





 531                         /*
 532                          * The class generation that we are waiting for should
 533                          * take a small, bounded time, so we can safely ignore
 534                          * thread interrupts here.
 535                          */



 536                     }
 537                     continue;
 538                 } else {
 539                     /*
 540                      * No proxy class for this list of interfaces has been
 541                      * generated or is being generated, so we will go and
 542                      * generate it now.  Mark it as pending generation.
 543                      */
 544                     cache.put(key, pendingGenerationMarker);
 545                     break;

 546                 }
 547             } while (true);
 548         }
 549 
 550         try {
 551             String proxyPkg = null;     // package to define proxy class in
 552             int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
 553 
 554             /*
 555              * Record the package of a non-public proxy interface so that the
 556              * proxy class will be defined in the same package.  Verify that
 557              * all non-public proxy interfaces are in the same package.
 558              */
 559             for (int i = 0; i < interfaces.length; i++) {
 560                 int flags = interfaces[i].getModifiers();
 561                 if (!Modifier.isPublic(flags)) {
 562                     accessFlags = Modifier.FINAL;
 563                     String name = interfaces[i].getName();
 564                     int n = name.lastIndexOf('.');
 565                     String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
 566                     if (proxyPkg == null) {
 567                         proxyPkg = pkg;
 568                     } else if (!pkg.equals(proxyPkg)) {
 569                         throw new IllegalArgumentException(
 570                             "non-public interfaces from different packages");
 571                     }
 572                 }
 573             }
 574 
 575             if (proxyPkg == null) {
 576                 // if no non-public proxy interfaces, use com.sun.proxy package
 577                 proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
 578             }
 579 
 580             {
 581                 /*
 582                  * Choose a name for the proxy class to generate.
 583                  */
 584                 long num;
 585                 synchronized (nextUniqueNumberLock) {
 586                     num = nextUniqueNumber++;
 587                 }
 588                 String proxyName = proxyPkg + proxyClassNamePrefix + num;
 589                 /*
 590                  * Verify that the class loader hasn't already
 591                  * defined a class with the chosen name.
 592                  */
 593 
 594                 /*
 595                  * Generate the specified proxy class.
 596                  */
 597                 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
 598                     proxyName, interfaces, accessFlags);
 599                 try {
 600                     proxyClass = defineClass0(loader, proxyName,
 601                         proxyClassFile, 0, proxyClassFile.length);
 602                 } catch (ClassFormatError e) {
 603                     /*
 604                      * A ClassFormatError here means that (barring bugs in the
 605                      * proxy class generation code) there was some other
 606                      * invalid aspect of the arguments supplied to the proxy
 607                      * class creation (such as virtual machine limitations
 608                      * exceeded).
 609                      */
 610                     throw new IllegalArgumentException(e.toString());
 611                 }
 612             }
 613             // add to set of all generated proxy classes, for isProxyClass
 614             proxyClasses.put(proxyClass, null);
 615 
 616         } finally {
 617             /*
 618              * We must clean up the "pending generation" state of the proxy
 619              * class cache entry somehow.  If a proxy class was successfully
 620              * generated, store it in the cache (with a weak reference);
 621              * otherwise, remove the reserved entry.  In all cases, notify
 622              * all waiters on reserved entries in this cache.
 623              */
 624             synchronized (cache) {
 625                 if (proxyClass != null) {
 626                     cache.put(key, new WeakReference<Class<?>>(proxyClass));
 627                 } else {
 628                     cache.remove(key);
 629                 }
 630                 cache.notifyAll();
 631             }
 632         }
 633         return proxyClass;
 634     }
 635 
 636     /**
 637      * Returns an instance of a proxy class for the specified interfaces
 638      * that dispatches method invocations to the specified invocation
 639      * handler.
 640      *
 641      * <p>{@code Proxy.newProxyInstance} throws
 642      * {@code IllegalArgumentException} for the same reasons that
 643      * {@code Proxy.getProxyClass} does.
 644      *
 645      * @param   loader the class loader to define the proxy class
 646      * @param   interfaces the list of interfaces for the proxy class
 647      *          to implement
 648      * @param   h the invocation handler to dispatch method invocations to
 649      * @return  a proxy instance with the specified invocation handler of a
 650      *          proxy class that is defined by the specified class loader
 651      *          and that implements the specified interfaces
 652      * @throws  IllegalArgumentException if any of the restrictions on the
 653      *          parameters that may be passed to {@code getProxyClass}


 740                 return;
 741             }
 742 
 743             ClassLoader ccl = caller.getClassLoader();
 744             ClassLoader pcl = proxyClass.getClassLoader();
 745 
 746             // do permission check if the caller is in a different runtime package
 747             // of the proxy class
 748             int n = pcn.lastIndexOf('.');
 749             String pkg = (n == -1) ? "" : pcn.substring(0, n);
 750 
 751             n = caller.getName().lastIndexOf('.');
 752             String callerPkg = (n == -1) ? "" : caller.getName().substring(0, n);
 753 
 754             if (pcl != ccl || !pkg.equals(callerPkg)) {
 755                 sm.checkPermission(new ReflectPermission("newProxyInPackage." + pkg));
 756             }
 757         }
 758     }
 759 
 760     private static Object newInstance(Constructor<?> cons, InvocationHandler h) {
 761         try {
 762             return cons.newInstance(new Object[] {h} );
 763         } catch (IllegalAccessException | InstantiationException e) {
 764             throw new InternalError(e.toString(), e);
 765         } catch (InvocationTargetException e) {
 766             Throwable t = e.getCause();
 767             if (t instanceof RuntimeException) {
 768                 throw (RuntimeException) t;
 769             } else {
 770                 throw new InternalError(t.toString(), t);
 771             }
 772         }
 773     }
 774 
 775     /**
 776      * Returns true if and only if the specified class was dynamically
 777      * generated to be a proxy class using the {@code getProxyClass}
 778      * method or the {@code newProxyInstance} method.
 779      *
 780      * <p>The reliability of this method is important for the ability
 781      * to use it to make security decisions, so its implementation should
 782      * not just test if the class in question extends {@code Proxy}.
 783      *
 784      * @param   cl the class to test
 785      * @return  {@code true} if the class is a proxy class and
 786      *          {@code false} otherwise
 787      * @throws  NullPointerException if {@code cl} is {@code null}
 788      */
 789     public static boolean isProxyClass(Class<?> cl) {
 790         if (cl == null) {
 791             throw new NullPointerException();
 792         }
 793 
 794         return proxyClasses.containsKey(cl);
 795     }
 796 
 797     /**
 798      * Returns the invocation handler for the specified proxy instance.
 799      *
 800      * @param   proxy the proxy instance to return the invocation handler for
 801      * @return  the invocation handler for the proxy instance
 802      * @throws  IllegalArgumentException if the argument is not a
 803      *          proxy instance
 804      */
 805     public static InvocationHandler getInvocationHandler(Object proxy)
 806         throws IllegalArgumentException
 807     {
 808         /*
 809          * Verify that the object is actually a proxy instance.
 810          */
 811         if (!isProxyClass(proxy.getClass())) {
 812             throw new IllegalArgumentException("not a proxy instance");
 813         }
 814 


   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  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.concurrent.atomic.AtomicLong;
  35 import java.util.function.BiFunction;

  36 import sun.misc.ProxyGenerator;
  37 import sun.misc.VM;
  38 import sun.reflect.CallerSensitive;
  39 import sun.reflect.Reflection;
  40 import sun.reflect.misc.ReflectUtil;
  41 import sun.security.util.SecurityConstants;
  42 
  43 /**
  44  * {@code Proxy} provides static methods for creating dynamic proxy
  45  * classes and instances, and it is also the superclass of all
  46  * dynamic proxy classes created by those methods.
  47  *
  48  * <p>To create a proxy for some interface {@code Foo}:
  49  * <pre>
  50  *     InvocationHandler handler = new MyInvocationHandler(...);
  51  *     Class&lt;?&gt; proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), Foo.class);
  52  *     Foo f = (Foo) proxyClass.getConstructor(InvocationHandler.class).
  53  *                     newInstance(handler);
  54  * </pre>
  55  * or more simply:


 211  * types in the {@code throws} clause of the method in <i>all</i> of
 212  * the proxy interfaces that it can be invoked through.  If the
 213  * {@code invoke} method throws a checked exception that is not
 214  * assignable to any of the exception types declared by the method in one
 215  * of the proxy interfaces that it can be invoked through, then an
 216  * unchecked {@code UndeclaredThrowableException} will be thrown by
 217  * the invocation on the proxy instance.  This restriction means that not
 218  * all of the exception types returned by invoking
 219  * {@code getExceptionTypes} on the {@code Method} object
 220  * passed to the {@code invoke} method can necessarily be thrown
 221  * successfully by the {@code invoke} method.
 222  *
 223  * @author      Peter Jones
 224  * @see         InvocationHandler
 225  * @since       1.3
 226  */
 227 public class Proxy implements java.io.Serializable {
 228 
 229     private static final long serialVersionUID = -2222568056686623797L;
 230 



 231     /** parameter types of a proxy class constructor */
 232     private static final Class<?>[] constructorParams =
 233         { InvocationHandler.class };
 234 
 235     /**
 236      * a cache of proxy classes
 237      */
 238     private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
 239         proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());









 240 
 241     /**
 242      * the invocation handler for this proxy instance.
 243      * @serial
 244      */
 245     protected InvocationHandler h;
 246 
 247     /**
 248      * Prohibits instantiation.
 249      */
 250     private Proxy() {
 251     }
 252 
 253     /**
 254      * Constructs a new {@code Proxy} instance from a subclass
 255      * (typically, a dynamic proxy class) with the specified value
 256      * for its invocation handler.
 257      *
 258      * @param   h the invocation handler for this proxy instance
 259      */


 390         SecurityManager sm = System.getSecurityManager();
 391         if (sm != null) {
 392             ClassLoader ccl = caller.getClassLoader();
 393             if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {
 394                 sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
 395             }
 396             ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
 397         }
 398     }
 399 
 400     /**
 401      * Generate a proxy class.  Must call the checkProxyAccess method
 402      * to perform permission checks before calling this.
 403      */
 404     private static Class<?> getProxyClass0(ClassLoader loader,
 405                                            Class<?>... interfaces) {
 406         if (interfaces.length > 65535) {
 407             throw new IllegalArgumentException("interface limit exceeded");
 408         }
 409 
 410         // If the proxy class defined by the given loader implementing
 411         // the given interfaces exists, this will simply return the cached copy;
 412         // otherwise, it will create the proxy class via the ProxyClassFactory
 413         return proxyClassCache.get(loader, interfaces);
 414     }
 415 
 416     /*
 417      * a key used for proxy class with 0 implemented interfaces
 418      */
 419     private static final Object key0 = new Object();
 420 
 421     /*
 422      * Key1 and Key2 are optimized for the common use of dynamic proxies
 423      * that implement 1 or 2 interfaces.
 424      */
 425 

 426     /*
 427      * a key used for proxy class with 1 implemented interface

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

 465 
 466         @Override
 467         public int hashCode() {
 468             return hash;
 469         }
 470 
 471         @Override
 472         public boolean equals(Object obj) {
 473             Class<?> intf1, intf2;
 474             return this == obj ||
 475                    obj != null &&
 476                    obj.getClass() == Key2.class &&
 477                    (intf1 = get()) != null &&
 478                    intf1 == ((Key2) obj).get() &&
 479                    (intf2 = ref2.get()) != null &&
 480                    intf2 == ((Key2) obj).ref2.get();
 481         }
 482     }
 483 
 484     /*
 485      * a key used for proxy class with any number of implemented interfaces
 486      * (used here for 3 or more only)
 487      */
 488     private static final class KeyX {
 489         private final int hash;
 490         private final WeakReference<Class<?>>[] refs;
 491 
 492         KeyX(Class<?>[] interfaces) {
 493             hash = Arrays.hashCode(interfaces);
 494             refs = new WeakReference[interfaces.length];
 495             for (int i = 0; i < interfaces.length; i++) {
 496                 refs[i] = new WeakReference<>(interfaces[i]);
 497             }
 498         }
 499 
 500         @Override
 501         public int hashCode() {
 502             return hash;
 503         }
 504 
 505         @Override
 506         public boolean equals(Object obj) {
 507             return this == obj ||
 508                    obj != null &&
 509                    obj.getClass() == KeyX.class &&
 510                    equals(refs, ((KeyX) obj).refs);
 511         }
 512 
 513         private static boolean equals(WeakReference<Class<?>>[] refs1,
 514                                       WeakReference<Class<?>>[] refs2) {
 515             if (refs1.length != refs2.length) {
 516                 return false;
 517             }
 518             for (int i = 0; i < refs1.length; i++) {
 519                 Class<?> intf = refs1[i].get();
 520                 if (intf == null || intf != refs2[i].get()) {
 521                     return false;
 522                 }
 523             }
 524             return true;
 525         }
 526     }
 527 
 528     /**
 529      * A function that maps an array of interfaces to an optimal key where
 530      * Class objects representing interfaces are weakly referenced.
 531      */
 532     private static final class KeyFactory
 533         implements BiFunction<ClassLoader, Class<?>[], Object>
 534     {
 535         @Override
 536         public Object apply(ClassLoader classLoader, Class<?>[] interfaces) {
 537             switch (interfaces.length) {
 538                 case 1: return new Key1(interfaces[0]); // the most frequent
 539                 case 2: return new Key2(interfaces[0], interfaces[1]);
 540                 case 0: return key0;
 541                 default: return new KeyX(interfaces);
 542             }
 543         }
 544     }
 545 
 546     /**
 547      * A factory function that generates, defines and returns the proxy class given
 548      * the ClassLoader and array of interfaces.







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



 567                  */
 568                 Class<?> interfaceClass = null;









 569                 try {
 570                     interfaceClass = Class.forName(intf.getName(), false, loader);
 571                 } catch (ClassNotFoundException e) {
 572                 }
 573                 if (interfaceClass != intf) {
 574                     throw new IllegalArgumentException(
 575                         intf + " is not visible from class loader");
 576                 }
 577                 /*
 578                  * Verify that the Class object actually represents an
 579                  * interface.

 580                  */
 581                 if (!interfaceClass.isInterface()) {
 582                     throw new IllegalArgumentException(
 583                         interfaceClass.getName() + " is not an interface");
 584                 }


 585                 /*
 586                  * Verify that this interface is not a duplicate.


 587                  */
 588                 if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
 589                     throw new IllegalArgumentException(
 590                         "repeated interface: " + interfaceClass.getName());
 591                 }

 592             }
 593 

 594             String proxyPkg = null;     // package to define proxy class in
 595             int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
 596 
 597             /*
 598              * Record the package of a non-public proxy interface so that the
 599              * proxy class will be defined in the same package.  Verify that
 600              * all non-public proxy interfaces are in the same package.
 601              */
 602             for (Class<?> intf : interfaces) {
 603                 int flags = intf.getModifiers();
 604                 if (!Modifier.isPublic(flags)) {
 605                     accessFlags = Modifier.FINAL;
 606                     String name = intf.getName();
 607                     int n = name.lastIndexOf('.');
 608                     String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
 609                     if (proxyPkg == null) {
 610                         proxyPkg = pkg;
 611                     } else if (!pkg.equals(proxyPkg)) {
 612                         throw new IllegalArgumentException(
 613                             "non-public interfaces from different packages");
 614                     }
 615                 }
 616             }
 617 
 618             if (proxyPkg == null) {
 619                 // if no non-public proxy interfaces, use com.sun.proxy package
 620                 proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
 621             }
 622 

 623             /*
 624              * Choose a name for the proxy class to generate.
 625              */
 626             long num = nextUniqueNumber.getAndIncrement();



 627             String proxyName = proxyPkg + proxyClassNamePrefix + num;




 628 
 629             /*
 630              * Generate the specified proxy class.
 631              */
 632             byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
 633                 proxyName, interfaces, accessFlags);
 634             try {
 635                 return defineClass0(loader, proxyName,
 636                                     proxyClassFile, 0, proxyClassFile.length);
 637             } catch (ClassFormatError e) {
 638                 /*
 639                  * A ClassFormatError here means that (barring bugs in the
 640                  * proxy class generation code) there was some other
 641                  * invalid aspect of the arguments supplied to the proxy
 642                  * class creation (such as virtual machine limitations
 643                  * exceeded).
 644                  */
 645                 throw new IllegalArgumentException(e.toString());
 646             }
 647         }





















 648     }
 649 
 650     /**
 651      * Returns an instance of a proxy class for the specified interfaces
 652      * that dispatches method invocations to the specified invocation
 653      * handler.
 654      *
 655      * <p>{@code Proxy.newProxyInstance} throws
 656      * {@code IllegalArgumentException} for the same reasons that
 657      * {@code Proxy.getProxyClass} does.
 658      *
 659      * @param   loader the class loader to define the proxy class
 660      * @param   interfaces the list of interfaces for the proxy class
 661      *          to implement
 662      * @param   h the invocation handler to dispatch method invocations to
 663      * @return  a proxy instance with the specified invocation handler of a
 664      *          proxy class that is defined by the specified class loader
 665      *          and that implements the specified interfaces
 666      * @throws  IllegalArgumentException if any of the restrictions on the
 667      *          parameters that may be passed to {@code getProxyClass}


 754                 return;
 755             }
 756 
 757             ClassLoader ccl = caller.getClassLoader();
 758             ClassLoader pcl = proxyClass.getClassLoader();
 759 
 760             // do permission check if the caller is in a different runtime package
 761             // of the proxy class
 762             int n = pcn.lastIndexOf('.');
 763             String pkg = (n == -1) ? "" : pcn.substring(0, n);
 764 
 765             n = caller.getName().lastIndexOf('.');
 766             String callerPkg = (n == -1) ? "" : caller.getName().substring(0, n);
 767 
 768             if (pcl != ccl || !pkg.equals(callerPkg)) {
 769                 sm.checkPermission(new ReflectPermission("newProxyInPackage." + pkg));
 770             }
 771         }
 772     }
 773 















 774     /**
 775      * Returns true if and only if the specified class was dynamically
 776      * generated to be a proxy class using the {@code getProxyClass}
 777      * method or the {@code newProxyInstance} method.
 778      *
 779      * <p>The reliability of this method is important for the ability
 780      * to use it to make security decisions, so its implementation should
 781      * not just test if the class in question extends {@code Proxy}.
 782      *
 783      * @param   cl the class to test
 784      * @return  {@code true} if the class is a proxy class and
 785      *          {@code false} otherwise
 786      * @throws  NullPointerException if {@code cl} is {@code null}
 787      */
 788     public static boolean isProxyClass(Class<?> cl) {
 789         return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);




 790     }
 791 
 792     /**
 793      * Returns the invocation handler for the specified proxy instance.
 794      *
 795      * @param   proxy the proxy instance to return the invocation handler for
 796      * @return  the invocation handler for the proxy instance
 797      * @throws  IllegalArgumentException if the argument is not a
 798      *          proxy instance
 799      */
 800     public static InvocationHandler getInvocationHandler(Object proxy)
 801         throws IllegalArgumentException
 802     {
 803         /*
 804          * Verify that the object is actually a proxy instance.
 805          */
 806         if (!isProxyClass(proxy.getClass())) {
 807             throw new IllegalArgumentException("not a proxy instance");
 808         }
 809