< prev index next >

src/java.base/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.WeakReference;
  29 import java.security.AccessController;
  30 import java.security.PrivilegedAction;
  31 import java.util.Arrays;
  32 import java.util.Collections;
  33 import java.util.Deque;
  34 import java.util.HashMap;
  35 import java.util.HashSet;
  36 import java.util.IdentityHashMap;
  37 import java.util.LinkedList;
  38 import java.util.List;
  39 import java.util.Map;
  40 import java.util.Objects;
  41 import java.util.Set;
  42 import java.util.WeakHashMap;
  43 import java.util.concurrent.atomic.AtomicInteger;
  44 import java.util.concurrent.atomic.AtomicLong;
  45 import java.util.function.BiFunction;
  46 import java.util.stream.Collectors;
  47 import java.util.stream.Stream;
  48 
  49 import jdk.internal.loader.BootLoader;
  50 import jdk.internal.module.Modules;
  51 import jdk.internal.misc.Unsafe;
  52 import jdk.internal.misc.VM;
  53 import sun.reflect.CallerSensitive;
  54 import sun.reflect.Reflection;
  55 import sun.reflect.misc.ReflectUtil;
  56 import sun.security.util.SecurityConstants;
  57 
  58 /**
  59  *
  60  * {@code Proxy} provides static methods for creating objects that act like instances
  61  * of interfaces but allow for customized method invocation.
  62  * To create a proxy instance for some interface {@code Foo}:
  63  * <pre>{@code
  64  *     InvocationHandler handler = new MyInvocationHandler(...);
  65  *     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),


 267  * of the proxy interfaces that it can be invoked through, then an
 268  * unchecked {@code UndeclaredThrowableException} will be thrown by
 269  * the invocation on the proxy instance.  This restriction means that not
 270  * all of the exception types returned by invoking
 271  * {@code getExceptionTypes} on the {@code Method} object
 272  * passed to the {@code invoke} method can necessarily be thrown
 273  * successfully by the {@code invoke} method.
 274  *
 275  * @author      Peter Jones
 276  * @see         InvocationHandler
 277  * @since       1.3
 278  */
 279 public class Proxy implements java.io.Serializable {
 280     private static final long serialVersionUID = -2222568056686623797L;
 281 
 282     /** parameter types of a proxy class constructor */
 283     private static final Class<?>[] constructorParams =
 284         { InvocationHandler.class };
 285 
 286     /**







 287      * the invocation handler for this proxy instance.
 288      * @serial
 289      */
 290     protected InvocationHandler h;
 291 
 292     /**
 293      * Prohibits instantiation.
 294      */
 295     private Proxy() {
 296     }
 297 
 298     /**
 299      * Constructs a new {@code Proxy} instance from a subclass
 300      * (typically, a dynamic proxy class) with the specified value
 301      * for its invocation handler.
 302      *
 303      * @param  h the invocation handler for this proxy instance
 304      *
 305      * @throws NullPointerException if the given invocation handler, {@code h},
 306      *         is {@code null}.


 344      *             s.checkPackageAccess()} denies access to {@code intf}.</li>
 345      *          </ul>
 346      * @throws  NullPointerException if the {@code interfaces} array
 347      *          argument or any of its elements are {@code null}
 348      *
 349      * @deprecated Proxy classes generated in a named module are encapsulated and not
 350      *      accessible to code outside its module.
 351      *      {@link Constructor#newInstance(Object...) Constructor.newInstance} will throw
 352      *      {@code IllegalAccessException} when it is called on an inaccessible proxy class.
 353      *      Use {@link #newProxyInstance(ClassLoader, Class[], InvocationHandler)}
 354      *      to create a proxy instance instead.
 355      *
 356      * @see <a href="#membership">Package and Module Membership of Proxy Class</a>
 357      */
 358     @Deprecated
 359     @CallerSensitive
 360     public static Class<?> getProxyClass(ClassLoader loader,
 361                                          Class<?>... interfaces)
 362         throws IllegalArgumentException
 363     {
 364         final List<Class<?>> intfs = List.of(interfaces);  // interfaces cloned
 365         final SecurityManager sm = System.getSecurityManager();
 366         final Class<?> caller = Reflection.getCallerClass();
 367         if (sm != null) {
 368             checkProxyAccess(caller, loader, intfs);

 369         }
 370 
 371         return new ProxyBuilder(loader, intfs).build();


























 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.
 391      */
 392     private static void checkProxyAccess(Class<?> caller,
 393                                          ClassLoader loader,
 394                                          List<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.toArray(EMPTY_CLASS_ARRAY));
 403         }
 404     }
 405 
 406     /*
 407      * a key used for proxy class with 0 implemented interfaces
 408      */
 409     private static final Object key0 = new Object();
 410 
 411     /*
 412      * Key1 and Key2 are optimized for the common use of dynamic proxies
 413      * that implement 1 or 2 interfaces.
 414      */
 415 
 416     /*
 417      * a key used for proxy class with 1 implemented interface
 418      */
 419     private static final class Key1 extends WeakReference<Class<?>> {
 420         private final int hash;
 421 
 422         Key1(Class<?> intf) {
 423             super(intf);
 424             this.hash = intf.hashCode();
 425         }
 426 
 427         @Override
 428         public int hashCode() {
 429             return hash;
 430         }
 431 
 432         @Override
 433         public boolean equals(Object obj) {
 434             Class<?> intf;
 435             return this == obj ||
 436                    obj != null &&
 437                    obj.getClass() == Key1.class &&
 438                    (intf = get()) != null &&
 439                    intf == ((Key1) obj).get();
 440         }
 441     }
 442 
 443     /*
 444      * a key used for proxy class with 2 implemented interfaces
 445      */
 446     private static final class Key2 extends WeakReference<Class<?>> {
 447         private final int hash;
 448         private final WeakReference<Class<?>> ref2;
 449 
 450         Key2(Class<?> intf1, Class<?> intf2) {
 451             super(intf1);
 452             hash = 31 * intf1.hashCode() + intf2.hashCode();
 453             ref2 = new WeakReference<>(intf2);
 454         }
 455 
 456         @Override
 457         public int hashCode() {
 458             return hash;
 459         }
 460 
 461         @Override
 462         public boolean equals(Object obj) {
 463             Class<?> intf1, intf2;
 464             return this == obj ||
 465                    obj != null &&
 466                    obj.getClass() == Key2.class &&
 467                    (intf1 = get()) != null &&
 468                    intf1 == ((Key2) obj).get() &&
 469                    (intf2 = ref2.get()) != null &&
 470                    intf2 == ((Key2) obj).ref2.get();
 471         }
 472     }
 473 
 474     /*
 475      * a key used for proxy class with any number of implemented interfaces
 476      * (used here for 3 or more only)
 477      */
 478     private static final class KeyX {
 479         private final int hash;
 480         private final WeakReference<Class<?>>[] refs;
 481 
 482         @SuppressWarnings("unchecked")
 483         KeyX(List<Class<?>> interfaces) {
 484             hash = Arrays.hashCode(interfaces.toArray());
 485             refs = (WeakReference<Class<?>>[])new WeakReference<?>[interfaces.size()];
 486             int i = 0;
 487             for (Class<?> intf : interfaces) {
 488                 refs[i++] = new WeakReference<>(intf);
 489             }
 490         }
 491 
 492         @Override
 493         public int hashCode() {
 494             return hash;
 495         }
 496 
 497         @Override
 498         public boolean equals(Object obj) {
 499             return this == obj ||
 500                    obj != null &&
 501                    obj.getClass() == KeyX.class &&
 502                    equals(refs, ((KeyX) obj).refs);
 503         }
 504 
 505         private static boolean equals(WeakReference<Class<?>>[] refs1,
 506                                       WeakReference<Class<?>>[] refs2) {
 507             if (refs1.length != refs2.length) {
 508                 return false;
 509             }
 510             for (int i = 0; i < refs1.length; i++) {
 511                 Class<?> intf = refs1[i].get();
 512                 if (intf == null || intf != refs2[i].get()) {
 513                     return false;
 514                 }
 515             }
 516             return true;
 517         }
 518     }
 519 
 520     /**
 521      * A function that maps an array of interfaces to an optimal key where
 522      * Class objects representing interfaces are weakly referenced.
 523      */
 524     private static final class KeyFactory<T>
 525         implements BiFunction<T, List<Class<?>>, Object>
 526     {
 527         @Override
 528         public Object apply(T t, List<Class<?>> interfaces) {
 529             switch (interfaces.size()) {
 530                 case 1: return new Key1(interfaces.get(0)); // the most frequent
 531                 case 2: return new Key2(interfaces.get(0), interfaces.get(1));
 532                 case 0: return key0;
 533                 default: return new KeyX(interfaces);
 534             }
 535         }
 536     }
 537 
 538     /**
 539      * A factory function that generates, defines and returns the proxy class
 540      * given the ClassLoader and array of interfaces.



 541      */
 542     private static final class ProxyClassFactory {
 543         private static final Unsafe UNSAFE = Unsafe.getUnsafe();
 544 
 545         // prefix for all proxy class names
 546         private static final String proxyClassNamePrefix = "$Proxy";
 547 
 548         // next number to use for generation of unique proxy class names
 549         private static final AtomicLong nextUniqueNumber = new AtomicLong();
 550 




 551         private static Class<?> defineProxyClass(Module m, List<Class<?>> interfaces) {
 552             String proxyPkg = null;     // package to define proxy class in
 553             int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
 554 
 555             /*
 556              * Record the package of a non-public proxy interface so that the
 557              * proxy class will be defined in the same package.  Verify that
 558              * all non-public proxy interfaces are in the same package.
 559              */
 560             for (Class<?> intf : interfaces) {
 561                 int flags = intf.getModifiers();
 562                 if (!Modifier.isPublic(flags)) {
 563                     accessFlags = Modifier.FINAL;  // non-public, final
 564                     String pkg = intf.getPackageName();
 565                     if (proxyPkg == null) {
 566                         proxyPkg = pkg;
 567                     } else if (!pkg.equals(proxyPkg)) {
 568                         throw new IllegalArgumentException(
 569                                 "non-public interfaces from different packages");
 570                     }


 584             if (m.isNamed()) {
 585                 m.addPackage(proxyPkg);
 586             }
 587 
 588             /*
 589              * Choose a name for the proxy class to generate.
 590              */
 591             long num = nextUniqueNumber.getAndIncrement();
 592             String proxyName = proxyPkg.isEmpty() ? proxyClassNamePrefix + num
 593                                                   : proxyPkg + "." + proxyClassNamePrefix + num;
 594 
 595             ClassLoader loader = getLoader(m);
 596             trace(proxyName, m, loader, interfaces);
 597 
 598             /*
 599              * Generate the specified proxy class.
 600              */
 601             byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
 602                     proxyName, interfaces.toArray(EMPTY_CLASS_ARRAY), accessFlags);
 603             try {
 604                 return UNSAFE.defineClass(proxyName, proxyClassFile, 0, proxyClassFile.length,

 605                                           loader, null);


 606             } catch (ClassFormatError e) {
 607                 /*
 608                  * A ClassFormatError here means that (barring bugs in the
 609                  * proxy class generation code) there was some other
 610                  * invalid aspect of the arguments supplied to the proxy
 611                  * class creation (such as virtual machine limitations
 612                  * exceeded).
 613                  */
 614                 throw new IllegalArgumentException(e.toString());
 615             }
 616         }
 617 
 618         /**
 619          * Test if the given class is a proxy class

 620          */
 621         static boolean isProxyClass(Class<?> c) {
 622             return proxyCache.containsValue(c);
 623         }
 624 
 625         /**
 626          * Returns the proxy class.  It will return the cached proxy class
 627          * if exists; otherwise, it will create the proxy class and store in
 628          * the cache.
 629          */
 630         static Class<?> get(Module module, List<Class<?>> interfaces) {
 631             return proxyCache.get(module, interfaces);
 632         }
 633 
 634         /**
 635          * a cache of proxy classes in the named and unnamed module
 636          */
 637         private static final WeakCache<Module, List<Class<?>>, Class<?>> proxyCache =
 638             new WeakCache<>(new KeyFactory<Module>(),
 639                 new BiFunction<Module, List<Class<?>>, Class<?>>()  {
 640                     @Override
 641                     public Class<?> apply(Module m, List<Class<?>> interfaces) {
 642                         Objects.requireNonNull(m);
 643                         return defineProxyClass(m, interfaces);
 644                     }
 645             });
 646 
 647 
 648         private static boolean isExportedType(Class<?> c) {
 649             String pn = c.getPackageName();
 650             return Modifier.isPublic(c.getModifiers()) && c.getModule().isExported(pn);
 651         }
 652 
 653         private static boolean isPackagePrivateType(Class<?> c) {
 654             return !Modifier.isPublic(c.getModifiers());
 655         }
 656 
 657         private static String toDetails(Class<?> c) {
 658             String access = "unknown";
 659             if (isExportedType(c)) {
 660                 access = "exported";
 661             } else if (isPackagePrivateType(c)) {
 662                 access = "package-private";
 663             } else {
 664                 access = "module-private";
 665             }
 666             ClassLoader ld = c.getClassLoader();
 667             return String.format("   %s/%s %s loader %s",
 668                     c.getModule().getName(), c.getName(), access, ld);
 669         }
 670 
 671         static void trace(String cn, Module module, ClassLoader loader, List<Class<?>> interfaces) {
 672             if (isDebug()) {
 673                 System.out.format("PROXY: %s/%s defined by %s%n", module.getName(), cn, loader);
 674             }
 675             if (isDebug("debug")) {
 676                 interfaces.stream()
 677                           .forEach(c -> System.out.println(toDetails(c)));
 678             }
 679         }
 680 
 681         private static final String DEBUG =
 682             AccessController.doPrivileged(new PrivilegedAction<>() {
 683                 public String run() {
 684                     return System.getProperty("jdk.proxy.debug", "");
 685                 }
 686             });
 687 
 688         private static final boolean isDebug() {
 689             return !DEBUG.isEmpty();
 690         }
 691         private static final boolean isDebug(String flag) {
 692             return DEBUG.equals(flag);
 693         }
 694     }
 695 
 696     /**
 697      * Builder for a proxy class.
 698      *
 699      * If the module is not specified in this ProxyBuilder constructor,
 700      * it will map from the given loader and interfaces to the module
 701      * in which the proxy class will be defined.
 702      */
 703     private static final class ProxyBuilder {
 704         final ClassLoader loader;
 705         final List<Class<?>> interfaces;
 706         final Module module;
 707         ProxyBuilder(ClassLoader loader, List<Class<?>> interfaces) {
 708             if (!VM.isModuleSystemInited()) {
 709                 throw new InternalError("Proxy is not supported until module system is fully initialzed");
 710             }
 711             if (interfaces.size() > 65535) {
 712                 throw new IllegalArgumentException("interface limit exceeded");
 713             }
 714 
 715             Set<Class<?>> refTypes = referencedTypes(loader, interfaces);
 716 
 717             // IAE if violates any restrictions specified in newProxyInstance
 718             validateProxyInterfaces(loader, interfaces, refTypes);
 719 
 720             this.loader = loader;
 721             this.interfaces = interfaces;
 722             this.module = mapToModule(loader, interfaces, refTypes);
 723             assert getLoader(module) == loader;
 724         }
 725 




 726         /**
 727          * Generate a proxy class.  If the target module does not have any

 728          * to any interface types, IllegalAccessError will be thrown by the VM
 729          * at defineClass time.
 730          *
 731          * Must call the checkProxyAccess method to perform permission checks
 732          * before calling this.
 733          */
 734         Class<?> build() {
 735             return ProxyClassFactory.get(module, interfaces);













 736         }
 737 
 738         /**
 739          * Validate the given proxy interfaces and the given referenced types
 740          * are visible to the defining loader.
 741          *
 742          * @throws IllegalArgumentException if it violates the restrictions specified
 743          *         in {@link Proxy#newProxyInstance}
 744          */
 745         static void validateProxyInterfaces(ClassLoader loader,
 746                                             List<Class<?>> interfaces,
 747                                             Set<Class<?>> refTypes)
 748         {
 749             Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.size());
 750             for (Class<?> intf : interfaces) {
 751                 /*
 752                  * Verify that the class loader resolves the name of this
 753                  * interface to the same Class object.
 754                  */
 755                 ensureVisible(loader, intf);
 756 
 757                 /*
 758                  * Verify that the Class object actually represents an
 759                  * interface.
 760                  */
 761                 if (!intf.isInterface()) {
 762                     throw new IllegalArgumentException(intf.getName() + " is not an interface");
 763                 }
 764 
 765                 /*
 766                  * Verify that this interface is not a duplicate.
 767                  */
 768                 if (interfaceSet.put(intf, Boolean.TRUE) != null) {
 769                     throw new IllegalArgumentException("repeated interface: " + intf.getName());
 770                 }
 771             }
 772 
 773             for (Class<?> type : refTypes) {
 774                 ensureVisible(loader, type);
 775             }
 776         }
 777 
 778         /*
 779          * Returns all types referenced by all public method signatures of
 780          * the proxy interfaces
 781          */
 782         static Set<Class<?>> referencedTypes(ClassLoader loader, List<Class<?>> interfaces) {

 783             return interfaces.stream()
 784                  .flatMap(intf -> Stream.of(intf.getMethods())
 785                                         .flatMap(m -> methodRefTypes(m))
 786                                         .map(ProxyBuilder::getElementType)
 787                                         .filter(t -> !t.isPrimitive()))
 788                  .collect(Collectors.toSet());
 789         }
 790 
 791         /*
 792          * Extracts all types referenced on a method signature including
 793          * its return type, parameter types, and exception types.
 794          */
 795         static Stream<Class<?>> methodRefTypes(Method m) {
 796             return Stream.of(new Class<?>[] { m.getReturnType() },
 797                              m.getParameterTypes(),
 798                              m.getExceptionTypes())
 799                          .flatMap(a -> Stream.of(a));
 800         }
 801 
 802         /**
 803          * Returns the module that the generated proxy class belongs to.
 804          *
 805          * If all proxy interfaces are public and in exported packages,
 806          * then the proxy class is in unnamed module.
 807          *
 808          * If any of proxy interface is package-private, then the proxy class
 809          * is in the same module of the package-private interface.
 810          *
 811          * If all proxy interfaces are public and at least one in a non-exported
 812          * package, then the proxy class is in a dynamic module in a non-exported
 813          * package.  Reads edge and qualified exports are added for
 814          * dynamic module to access.
 815          */
 816         static Module mapToModule(ClassLoader loader, List<Class<?>> interfaces, Set<Class<?>> refTypes) {


 817             Map<Class<?>, Module> modulePrivateTypes = new HashMap<>();
 818             Map<Class<?>, Module> packagePrivateTypes = new HashMap<>();
 819             for (Class<?> intf : interfaces) {
 820                 Module m = intf.getModule();
 821                 if (Modifier.isPublic(intf.getModifiers())) {
 822                     // module-private types
 823                     if (!m.isExported(intf.getPackageName())) {
 824                         modulePrivateTypes.put(intf, m);
 825                     }
 826                 } else {
 827                     packagePrivateTypes.put(intf, m);
 828                 }
 829             }
 830 
 831             // all proxy interfaces are public and exported, the proxy class is in unnamed module
 832             // Such proxy class is accessible to any unnamed module and named module that
 833             // can read unnamed module
 834             if (packagePrivateTypes.isEmpty() && modulePrivateTypes.isEmpty()) {
 835                 return loader != null ? loader.getUnnamedModule() : BootLoader.getUnnamedModule();
 836             }


 867                     if (m == target) continue;
 868 
 869                     if (!target.canRead(m) || !m.isExported(intf.getPackageName(), target)) {
 870                         throw new IllegalArgumentException(target + " can't access " + intf.getName());
 871                     }
 872                 }
 873 
 874                 // return the module of the package-private interface
 875                 return target;
 876             }
 877 
 878             // all proxy interfaces are public and at least one in a non-exported package
 879             // map to dynamic proxy module and add reads edge and qualified exports, if necessary
 880             Module target = getDynamicModule(loader);
 881 
 882             // set up proxy class access to proxy interfaces and superinterfaces
 883             Deque<Class<?>> deque = new LinkedList<>(interfaces);
 884             Set<Class<?>> visited = new HashSet<>();
 885             while (!deque.isEmpty()) {
 886                 Class<?> c = deque.poll();
 887                 if (visited.contains(c)) {
 888                     continue;
 889                 }
 890                 visited.add(c);
 891                 ensureAccess(target, c);
 892 
 893                 // add all superinterfaces
 894                 for (Class<?> intf : c.getInterfaces()) {
 895                     deque.add(intf);
 896                 }
 897             }
 898 
 899             // set up proxy class access to types referenced in the method signature
 900             refTypes.stream()
 901                     .filter(t -> !visited.contains(t))
 902                     .forEach(t -> ensureAccess(target, t));
 903             return target;
 904         }
 905 
 906         /*
 907          * Ensure the given module can access the given class.
 908          */
 909         static void ensureAccess(Module target, Class<?> c) {
 910             Module m = c.getModule();
 911             // add read edge and qualified export for the target module to access
 912             if (!target.canRead(m)) {
 913                 Modules.addReads(target, m);
 914             }
 915             String pn = c.getPackageName();
 916             if (!m.isExported(pn, target)) {
 917                 Modules.addExports(m, pn, target);
 918             }
 919         }
 920 
 921         /*
 922          * Ensure the given class is visible to the class loader.
 923          */
 924         static void ensureVisible(ClassLoader ld, Class<?> c) {
 925             Class<?> type = null;
 926             try {
 927                 type = Class.forName(c.getName(), false, ld);
 928             } catch (ClassNotFoundException e) {
 929             }
 930             if (type != c) {
 931                 throw new IllegalArgumentException(c.getName() +
 932                         " referenced from a method is not visible from class loader");
 933             }
 934         }
 935 
 936         static Class<?> getElementType(Class<?> type) {
 937             Class<?> e = type;
 938             while (e.isArray()) {
 939                 e = e.getComponentType();
 940             }
 941             return e;
 942         }
 943 
 944         private static final WeakHashMap<ClassLoader, Module> dynProxyModules = new WeakHashMap<>();

 945         private static final AtomicInteger counter = new AtomicInteger();
 946 
 947         /*
 948          * Define a dynamic module for the generated proxy classes in a non-exported package
 949          * named com.sun.proxy.$MODULE.
 950          *
 951          * Each class loader will have one dynamic module.
 952          */
 953         static Module getDynamicModule(ClassLoader loader) {
 954             return dynProxyModules.computeIfAbsent(loader, ld -> {
 955                 // create a dynamic module and setup module access
 956                 String mn = "jdk.proxy" + counter.incrementAndGet();
 957                 String pn = PROXY_PACKAGE_PREFIX + "." + mn;
 958                 Module m = Modules.defineModule(loader, mn, Collections.singleton(pn));
 959                 Modules.addReads(m, Proxy.class.getModule());
 960                 // java.base to create proxy instance
 961                 Modules.addExports(m, pn, Object.class.getModule());
 962                 return m;
 963             });
 964         }
 965     }
 966 
 967     /**
 968      * Returns a proxy instance for the specified interfaces
 969      * that dispatches method invocations to the specified invocation
 970      * handler.
 971      * <p>
 972      * <a name="restrictions">{@code IllegalArgumentException} will be thrown
 973      * if any of the following restrictions is violated:</a>
 974      * <ul>
 975      * <li>All of {@code Class} objects in the given {@code interfaces} array
 976      * must represent interfaces, not classes or primitive types.
 977      *
 978      * <li>No two elements in the {@code interfaces} array may


1045      *          <li> any of the given proxy interfaces is non-public and the
1046      *               caller class is not in the same {@linkplain Package runtime package}
1047      *               as the non-public interface and the invocation of
1048      *               {@link SecurityManager#checkPermission s.checkPermission} with
1049      *               {@code ReflectPermission("newProxyInPackage.{package name}")}
1050      *               permission denies access.</li>
1051      *          </ul>
1052      * @throws  NullPointerException if the {@code interfaces} array
1053      *          argument or any of its elements are {@code null}, or
1054      *          if the invocation handler, {@code h}, is
1055      *          {@code null}
1056      *
1057      * @see <a href="#membership">Package and Module Membership of Proxy Class</a>
1058      */
1059     @CallerSensitive
1060     public static Object newProxyInstance(ClassLoader loader,
1061                                           Class<?>[] interfaces,
1062                                           InvocationHandler h) {
1063         Objects.requireNonNull(h);
1064 
1065         final List<Class<?>> intfs = List.of(interfaces);  // interfaces cloned
1066         final SecurityManager sm = System.getSecurityManager();
1067         final Class<?> caller = Reflection.getCallerClass();
1068         if (sm != null) {
1069             checkProxyAccess(caller, loader, intfs);
1070         }
1071 
1072         /*
1073          * Look up or generate the designated proxy class.
1074          */
1075         Class<?> cl = new ProxyBuilder(loader, intfs).build();
1076 
1077         return newProxyInstance(cl, caller, h);
1078     }
1079 
1080     private static Object newProxyInstance(Class<?> proxyClass, Class<?> caller, InvocationHandler h) {


1081         /*
1082          * Invoke its constructor with the designated invocation handler.
1083          */
1084         try {
1085             final SecurityManager sm = System.getSecurityManager();
1086             if (sm != null) {
1087                 checkNewProxyPermission(caller, proxyClass);
1088             }
1089 
1090             final Constructor<?> cons = proxyClass.getConstructor(constructorParams);
1091             AccessController.doPrivileged(new PrivilegedAction<Void>() {
1092                 public Void run() {
1093                     cons.setAccessible(true);
1094                     return null;
1095                 }
1096             });
1097             return cons.newInstance(new Object[]{h});
1098         } catch (IllegalAccessException | InstantiationException | NoSuchMethodException e) {
1099             throw new InternalError(e.toString(), e);
1100         } catch (InvocationTargetException e) {
1101             Throwable t = e.getCause();
1102             if (t instanceof RuntimeException) {
1103                 throw (RuntimeException) t;
1104             } else {
1105                 throw new InternalError(t.toString(), t);
1106             }
1107         }
1108     }
1109 
1110     private static void checkNewProxyPermission(Class<?> caller, Class<?> proxyClass) {
1111         SecurityManager sm = System.getSecurityManager();
1112         if (sm != null) {
1113             if (ReflectUtil.isNonPublicProxyClass(proxyClass)) {
1114                 ClassLoader ccl = caller.getClassLoader();
1115                 ClassLoader pcl = proxyClass.getClassLoader();
1116 
1117                 // do permission check if the caller is in a different runtime package
1118                 // of the proxy class


1133      * Returns the class loader for the given module.
1134      */
1135     private static ClassLoader getLoader(Module m) {
1136         PrivilegedAction<ClassLoader> pa = m::getClassLoader;
1137         return AccessController.doPrivileged(pa);
1138     }
1139 
1140     /**
1141      * Returns true if the given class is a proxy class.
1142      *
1143      * @implNote The reliability of this method is important for the ability
1144      * to use it to make security decisions, so its implementation should
1145      * not just test if the class in question extends {@code Proxy}.
1146      *
1147      * @param   cl the class to test
1148      * @return  {@code true} if the class is a proxy class and
1149      *          {@code false} otherwise
1150      * @throws  NullPointerException if {@code cl} is {@code null}
1151      */
1152     public static boolean isProxyClass(Class<?> cl) {
1153         return Proxy.class.isAssignableFrom(cl) && ProxyClassFactory.isProxyClass(cl);
1154     }
1155 
1156     /**
1157      * Returns the invocation handler for the specified proxy instance.
1158      *
1159      * @param   proxy the proxy instance to return the invocation handler for
1160      * @return  the invocation handler for the proxy instance
1161      * @throws  IllegalArgumentException if the argument is not a
1162      *          proxy instance
1163      * @throws  SecurityException if a security manager, <em>s</em>, is present
1164      *          and the caller's class loader is not the same as or an
1165      *          ancestor of the class loader for the invocation handler
1166      *          and invocation of {@link SecurityManager#checkPackageAccess
1167      *          s.checkPackageAccess()} denies access to the invocation
1168      *          handler's class.
1169      */
1170     @CallerSensitive
1171     public static InvocationHandler getInvocationHandler(Object proxy)
1172         throws IllegalArgumentException
1173     {




   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.security.AccessController;
  29 import java.security.PrivilegedAction;
  30 import java.util.Arrays;
  31 import java.util.Collections;
  32 import java.util.Deque;
  33 import java.util.HashMap;
  34 import java.util.HashSet;
  35 import java.util.IdentityHashMap;
  36 import java.util.LinkedList;
  37 import java.util.List;
  38 import java.util.Map;
  39 import java.util.Objects;
  40 import java.util.Set;

  41 import java.util.concurrent.atomic.AtomicInteger;
  42 import java.util.concurrent.atomic.AtomicLong;

  43 import java.util.stream.Collectors;
  44 import java.util.stream.Stream;
  45 
  46 import jdk.internal.loader.BootLoader;
  47 import jdk.internal.module.Modules;
  48 import jdk.internal.misc.Unsafe;
  49 import jdk.internal.misc.VM;
  50 import sun.reflect.CallerSensitive;
  51 import sun.reflect.Reflection;
  52 import sun.reflect.misc.ReflectUtil;
  53 import sun.security.util.SecurityConstants;
  54 
  55 /**
  56  *
  57  * {@code Proxy} provides static methods for creating objects that act like instances
  58  * of interfaces but allow for customized method invocation.
  59  * To create a proxy instance for some interface {@code Foo}:
  60  * <pre>{@code
  61  *     InvocationHandler handler = new MyInvocationHandler(...);
  62  *     Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),


 264  * of the proxy interfaces that it can be invoked through, then an
 265  * unchecked {@code UndeclaredThrowableException} will be thrown by
 266  * the invocation on the proxy instance.  This restriction means that not
 267  * all of the exception types returned by invoking
 268  * {@code getExceptionTypes} on the {@code Method} object
 269  * passed to the {@code invoke} method can necessarily be thrown
 270  * successfully by the {@code invoke} method.
 271  *
 272  * @author      Peter Jones
 273  * @see         InvocationHandler
 274  * @since       1.3
 275  */
 276 public class Proxy implements java.io.Serializable {
 277     private static final long serialVersionUID = -2222568056686623797L;
 278 
 279     /** parameter types of a proxy class constructor */
 280     private static final Class<?>[] constructorParams =
 281         { InvocationHandler.class };
 282 
 283     /**
 284      * a cache of proxy constructors with
 285      * {@link Constructor#setAccessible(boolean) accessible} flag already set
 286      */
 287     private static final ClassLoaderValue<Constructor<?>> proxyCache =
 288         new ClassLoaderValue<>();
 289 
 290     /**
 291      * the invocation handler for this proxy instance.
 292      * @serial
 293      */
 294     protected InvocationHandler h;
 295 
 296     /**
 297      * Prohibits instantiation.
 298      */
 299     private Proxy() {
 300     }
 301 
 302     /**
 303      * Constructs a new {@code Proxy} instance from a subclass
 304      * (typically, a dynamic proxy class) with the specified value
 305      * for its invocation handler.
 306      *
 307      * @param  h the invocation handler for this proxy instance
 308      *
 309      * @throws NullPointerException if the given invocation handler, {@code h},
 310      *         is {@code null}.


 348      *             s.checkPackageAccess()} denies access to {@code intf}.</li>
 349      *          </ul>
 350      * @throws  NullPointerException if the {@code interfaces} array
 351      *          argument or any of its elements are {@code null}
 352      *
 353      * @deprecated Proxy classes generated in a named module are encapsulated and not
 354      *      accessible to code outside its module.
 355      *      {@link Constructor#newInstance(Object...) Constructor.newInstance} will throw
 356      *      {@code IllegalAccessException} when it is called on an inaccessible proxy class.
 357      *      Use {@link #newProxyInstance(ClassLoader, Class[], InvocationHandler)}
 358      *      to create a proxy instance instead.
 359      *
 360      * @see <a href="#membership">Package and Module Membership of Proxy Class</a>
 361      */
 362     @Deprecated
 363     @CallerSensitive
 364     public static Class<?> getProxyClass(ClassLoader loader,
 365                                          Class<?>... interfaces)
 366         throws IllegalArgumentException
 367     {
 368         Class<?> caller = System.getSecurityManager() == null
 369                               ? null
 370                               : Reflection.getCallerClass();
 371 
 372         return getProxyConstructor(caller, loader, interfaces)
 373             .getDeclaringClass();
 374     }
 375 
 376     private static Constructor<?> getProxyConstructor(Class<?> caller, // null if no SecurityManager
 377                                                       ClassLoader loader,
 378                                                       Class<?>... interfaces)
 379         throws IllegalArgumentException
 380     {
 381         // optimization for single interface
 382         if (interfaces.length == 1) {
 383             Class<?> intf = interfaces[0];
 384             if (caller != null) {
 385                 checkProxyAccess(caller, loader, intf);
 386             }
 387             return proxyCache.sub(intf).computeIfAbsent(
 388                 loader,
 389                 (ld, clv) -> new ProxyBuilder(ld, clv.key()).build()
 390             );
 391         } else {
 392             // interfaces cloned
 393             final Class<?>[] intfsArray = interfaces.clone();
 394             if (caller != null) {
 395                 checkProxyAccess(caller, loader, intfsArray);
 396             }
 397             final List<Class<?>> intfs = Arrays.asList(intfsArray);
 398             return proxyCache.sub(intfs).computeIfAbsent(
 399                 loader,
 400                 (ld, clv) -> new ProxyBuilder(ld, clv.key()).build()
 401             );
 402         }
 403     }
 404 
 405     /*
 406      * Check permissions required to create a Proxy class.
 407      *
 408      * To define a proxy class, it performs the access checks as in
 409      * Class.forName (VM will invoke ClassLoader.checkPackageAccess):
 410      * 1. "getClassLoader" permission check if loader == null
 411      * 2. checkPackageAccess on the interfaces it implements
 412      *
 413      * To get a constructor and new instance of a proxy class, it performs
 414      * the package access check on the interfaces it implements
 415      * as in Class.getConstructor.
 416      *
 417      * If an interface is non-public, the proxy class must be defined by
 418      * the defining loader of the interface.  If the caller's class loader
 419      * is not the same as the defining loader of the interface, the VM
 420      * will throw IllegalAccessError when the generated proxy class is
 421      * being defined.
 422      */
 423     private static void checkProxyAccess(Class<?> caller,
 424                                          ClassLoader loader,
 425                                          Class<?> ... interfaces)
 426     {
 427         SecurityManager sm = System.getSecurityManager();
 428         if (sm != null) {
 429             ClassLoader ccl = caller.getClassLoader();
 430             if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {
 431                 sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
 432             }
 433             ReflectUtil.checkProxyPackageAccess(ccl, interfaces);




































































































































 434         }
 435     }
 436 
 437     /**
 438      * Builder for a proxy class.
 439      *
 440      * If the module is not specified in this ProxyBuilder constructor,
 441      * it will map from the given loader and interfaces to the module
 442      * in which the proxy class will be defined.
 443      */
 444     private static final class ProxyBuilder {
 445         private static final Unsafe UNSAFE = Unsafe.getUnsafe();
 446 
 447         // prefix for all proxy class names
 448         private static final String proxyClassNamePrefix = "$Proxy";
 449 
 450         // next number to use for generation of unique proxy class names
 451         private static final AtomicLong nextUniqueNumber = new AtomicLong();
 452 
 453         // a reverse cache of defined proxy classes
 454         private static final ClassLoaderValue<Boolean> reverseProxyCache =
 455             new ClassLoaderValue<>();
 456 
 457         private static Class<?> defineProxyClass(Module m, List<Class<?>> interfaces) {
 458             String proxyPkg = null;     // package to define proxy class in
 459             int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
 460 
 461             /*
 462              * Record the package of a non-public proxy interface so that the
 463              * proxy class will be defined in the same package.  Verify that
 464              * all non-public proxy interfaces are in the same package.
 465              */
 466             for (Class<?> intf : interfaces) {
 467                 int flags = intf.getModifiers();
 468                 if (!Modifier.isPublic(flags)) {
 469                     accessFlags = Modifier.FINAL;  // non-public, final
 470                     String pkg = intf.getPackageName();
 471                     if (proxyPkg == null) {
 472                         proxyPkg = pkg;
 473                     } else if (!pkg.equals(proxyPkg)) {
 474                         throw new IllegalArgumentException(
 475                                 "non-public interfaces from different packages");
 476                     }


 490             if (m.isNamed()) {
 491                 m.addPackage(proxyPkg);
 492             }
 493 
 494             /*
 495              * Choose a name for the proxy class to generate.
 496              */
 497             long num = nextUniqueNumber.getAndIncrement();
 498             String proxyName = proxyPkg.isEmpty() ? proxyClassNamePrefix + num
 499                                                   : proxyPkg + "." + proxyClassNamePrefix + num;
 500 
 501             ClassLoader loader = getLoader(m);
 502             trace(proxyName, m, loader, interfaces);
 503 
 504             /*
 505              * Generate the specified proxy class.
 506              */
 507             byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
 508                     proxyName, interfaces.toArray(EMPTY_CLASS_ARRAY), accessFlags);
 509             try {
 510                 Class<?> pc = UNSAFE.defineClass(proxyName, proxyClassFile,
 511                                                  0, proxyClassFile.length,
 512                                                  loader, null);
 513                 reverseProxyCache.sub(pc).putIfAbsent(loader, Boolean.TRUE);
 514                 return pc;
 515             } catch (ClassFormatError e) {
 516                 /*
 517                  * A ClassFormatError here means that (barring bugs in the
 518                  * proxy class generation code) there was some other
 519                  * invalid aspect of the arguments supplied to the proxy
 520                  * class creation (such as virtual machine limitations
 521                  * exceeded).
 522                  */
 523                 throw new IllegalArgumentException(e.toString());
 524             }
 525         }
 526 
 527         /**
 528          * Test if given class is a class defined by
 529          * {@link #defineProxyClass(Module, List)}
 530          */
 531         static boolean isProxyClass(Class<?> c) {
 532             return Boolean.TRUE.equals(
 533                 reverseProxyCache.sub(c).get(c.getClassLoader()));








 534         }
 535 














 536         private static boolean isExportedType(Class<?> c) {
 537             String pn = c.getPackageName();
 538             return Modifier.isPublic(c.getModifiers()) && c.getModule().isExported(pn);
 539         }
 540 
 541         private static boolean isPackagePrivateType(Class<?> c) {
 542             return !Modifier.isPublic(c.getModifiers());
 543         }
 544 
 545         private static String toDetails(Class<?> c) {
 546             String access = "unknown";
 547             if (isExportedType(c)) {
 548                 access = "exported";
 549             } else if (isPackagePrivateType(c)) {
 550                 access = "package-private";
 551             } else {
 552                 access = "module-private";
 553             }
 554             ClassLoader ld = c.getClassLoader();
 555             return String.format("   %s/%s %s loader %s",
 556                     c.getModule().getName(), c.getName(), access, ld);
 557         }
 558 
 559         static void trace(String cn, Module module, ClassLoader loader, List<Class<?>> interfaces) {
 560             if (isDebug()) {
 561                 System.out.format("PROXY: %s/%s defined by %s%n", module.getName(), cn, loader);
 562             }
 563             if (isDebug("debug")) {
 564                 interfaces.stream()
 565                           .forEach(c -> System.out.println(toDetails(c)));
 566             }
 567         }
 568 
 569         private static final String DEBUG =
 570             AccessController.doPrivileged(new PrivilegedAction<>() {
 571                 public String run() {
 572                     return System.getProperty("jdk.proxy.debug", "");
 573                 }
 574             });
 575 
 576         private static boolean isDebug() {
 577             return !DEBUG.isEmpty();
 578         }
 579         private static boolean isDebug(String flag) {
 580             return DEBUG.equals(flag);
 581         }

 582 
 583         // ProxyBuilder instance members start here....
 584 
 585         private final ClassLoader loader;
 586         private final List<Class<?>> interfaces;
 587         private final Module module;






 588         ProxyBuilder(ClassLoader loader, List<Class<?>> interfaces) {
 589             if (!VM.isModuleSystemInited()) {
 590                 throw new InternalError("Proxy is not supported until module system is fully initialzed");
 591             }
 592             if (interfaces.size() > 65535) {
 593                 throw new IllegalArgumentException("interface limit exceeded");
 594             }
 595 
 596             Set<Class<?>> refTypes = referencedTypes(loader, interfaces);
 597 
 598             // IAE if violates any restrictions specified in newProxyInstance
 599             validateProxyInterfaces(loader, interfaces, refTypes);
 600 
 601             this.loader = loader;
 602             this.interfaces = interfaces;
 603             this.module = mapToModule(loader, interfaces, refTypes);
 604             assert getLoader(module) == loader;
 605         }
 606 
 607         ProxyBuilder(ClassLoader loader, Class<?> intf) {
 608             this(loader, Collections.singletonList(intf));
 609         }
 610 
 611         /**
 612          * Generate a proxy class and return its proxy Constructor with
 613          * accessible flag already set. If the target module does not have access
 614          * to any interface types, IllegalAccessError will be thrown by the VM
 615          * at defineClass time.
 616          *
 617          * Must call the checkProxyAccess method to perform permission checks
 618          * before calling this.
 619          */
 620         Constructor<?> build() {
 621             Class<?> proxyClass = defineProxyClass(module, interfaces);
 622             final Constructor<?> cons;
 623             try {
 624                 cons = proxyClass.getConstructor(constructorParams);
 625             } catch (NoSuchMethodException e) {
 626                 throw new InternalError(e.toString(), e);
 627             }
 628             AccessController.doPrivileged(new PrivilegedAction<Void>() {
 629                 public Void run() {
 630                     cons.setAccessible(true);
 631                     return null;
 632                 }
 633             });
 634             return cons;
 635         }
 636 
 637         /**
 638          * Validate the given proxy interfaces and the given referenced types
 639          * are visible to the defining loader.
 640          *
 641          * @throws IllegalArgumentException if it violates the restrictions specified
 642          *         in {@link Proxy#newProxyInstance}
 643          */
 644         private static void validateProxyInterfaces(ClassLoader loader,
 645                                                     List<Class<?>> interfaces,
 646                                                     Set<Class<?>> refTypes)
 647         {
 648             Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.size());
 649             for (Class<?> intf : interfaces) {
 650                 /*
 651                  * Verify that the class loader resolves the name of this
 652                  * interface to the same Class object.
 653                  */
 654                 ensureVisible(loader, intf);
 655 
 656                 /*
 657                  * Verify that the Class object actually represents an
 658                  * interface.
 659                  */
 660                 if (!intf.isInterface()) {
 661                     throw new IllegalArgumentException(intf.getName() + " is not an interface");
 662                 }
 663 
 664                 /*
 665                  * Verify that this interface is not a duplicate.
 666                  */
 667                 if (interfaceSet.put(intf, Boolean.TRUE) != null) {
 668                     throw new IllegalArgumentException("repeated interface: " + intf.getName());
 669                 }
 670             }
 671 
 672             for (Class<?> type : refTypes) {
 673                 ensureVisible(loader, type);
 674             }
 675         }
 676 
 677         /*
 678          * Returns all types referenced by all public method signatures of
 679          * the proxy interfaces
 680          */
 681         private static Set<Class<?>> referencedTypes(ClassLoader loader,
 682                                                      List<Class<?>> interfaces) {
 683             return interfaces.stream()
 684                  .flatMap(intf -> Stream.of(intf.getMethods())
 685                                         .flatMap(ProxyBuilder::methodRefTypes)
 686                                         .map(ProxyBuilder::getElementType)
 687                                         .filter(t -> !t.isPrimitive()))
 688                  .collect(Collectors.toSet());
 689         }
 690 
 691         /*
 692          * Extracts all types referenced on a method signature including
 693          * its return type, parameter types, and exception types.
 694          */
 695         private static Stream<Class<?>> methodRefTypes(Method m) {
 696             return Stream.of(new Class<?>[] { m.getReturnType() },
 697                              m.getParameterTypes(),
 698                              m.getExceptionTypes())
 699                          .flatMap(Stream::of);
 700         }
 701 
 702         /**
 703          * Returns the module that the generated proxy class belongs to.
 704          *
 705          * If all proxy interfaces are public and in exported packages,
 706          * then the proxy class is in unnamed module.
 707          *
 708          * If any of proxy interface is package-private, then the proxy class
 709          * is in the same module of the package-private interface.
 710          *
 711          * If all proxy interfaces are public and at least one in a non-exported
 712          * package, then the proxy class is in a dynamic module in a non-exported
 713          * package.  Reads edge and qualified exports are added for
 714          * dynamic module to access.
 715          */
 716         private static Module mapToModule(ClassLoader loader,
 717                                           List<Class<?>> interfaces,
 718                                           Set<Class<?>> refTypes) {
 719             Map<Class<?>, Module> modulePrivateTypes = new HashMap<>();
 720             Map<Class<?>, Module> packagePrivateTypes = new HashMap<>();
 721             for (Class<?> intf : interfaces) {
 722                 Module m = intf.getModule();
 723                 if (Modifier.isPublic(intf.getModifiers())) {
 724                     // module-private types
 725                     if (!m.isExported(intf.getPackageName())) {
 726                         modulePrivateTypes.put(intf, m);
 727                     }
 728                 } else {
 729                     packagePrivateTypes.put(intf, m);
 730                 }
 731             }
 732 
 733             // all proxy interfaces are public and exported, the proxy class is in unnamed module
 734             // Such proxy class is accessible to any unnamed module and named module that
 735             // can read unnamed module
 736             if (packagePrivateTypes.isEmpty() && modulePrivateTypes.isEmpty()) {
 737                 return loader != null ? loader.getUnnamedModule() : BootLoader.getUnnamedModule();
 738             }


 769                     if (m == target) continue;
 770 
 771                     if (!target.canRead(m) || !m.isExported(intf.getPackageName(), target)) {
 772                         throw new IllegalArgumentException(target + " can't access " + intf.getName());
 773                     }
 774                 }
 775 
 776                 // return the module of the package-private interface
 777                 return target;
 778             }
 779 
 780             // all proxy interfaces are public and at least one in a non-exported package
 781             // map to dynamic proxy module and add reads edge and qualified exports, if necessary
 782             Module target = getDynamicModule(loader);
 783 
 784             // set up proxy class access to proxy interfaces and superinterfaces
 785             Deque<Class<?>> deque = new LinkedList<>(interfaces);
 786             Set<Class<?>> visited = new HashSet<>();
 787             while (!deque.isEmpty()) {
 788                 Class<?> c = deque.poll();
 789                 if (!visited.add(c)) {
 790                     continue;
 791                 }

 792                 ensureAccess(target, c);
 793 
 794                 // add all superinterfaces
 795                 for (Class<?> intf : c.getInterfaces()) {
 796                     deque.add(intf);
 797                 }
 798             }
 799 
 800             // set up proxy class access to types referenced in the method signature
 801             refTypes.stream()
 802                     .filter(t -> !visited.contains(t))
 803                     .forEach(t -> ensureAccess(target, t));
 804             return target;
 805         }
 806 
 807         /*
 808          * Ensure the given module can access the given class.
 809          */
 810         private static void ensureAccess(Module target, Class<?> c) {
 811             Module m = c.getModule();
 812             // add read edge and qualified export for the target module to access
 813             if (!target.canRead(m)) {
 814                 Modules.addReads(target, m);
 815             }
 816             String pn = c.getPackageName();
 817             if (!m.isExported(pn, target)) {
 818                 Modules.addExports(m, pn, target);
 819             }
 820         }
 821 
 822         /*
 823          * Ensure the given class is visible to the class loader.
 824          */
 825         private static void ensureVisible(ClassLoader ld, Class<?> c) {
 826             Class<?> type = null;
 827             try {
 828                 type = Class.forName(c.getName(), false, ld);
 829             } catch (ClassNotFoundException e) {
 830             }
 831             if (type != c) {
 832                 throw new IllegalArgumentException(c.getName() +
 833                         " referenced from a method is not visible from class loader");
 834             }
 835         }
 836 
 837         private static Class<?> getElementType(Class<?> type) {
 838             Class<?> e = type;
 839             while (e.isArray()) {
 840                 e = e.getComponentType();
 841             }
 842             return e;
 843         }
 844 
 845         private static final ClassLoaderValue<Module> dynProxyModules =
 846             new ClassLoaderValue<>();
 847         private static final AtomicInteger counter = new AtomicInteger();
 848 
 849         /*
 850          * Define a dynamic module for the generated proxy classes in a non-exported package
 851          * named com.sun.proxy.$MODULE.
 852          *
 853          * Each class loader will have one dynamic module.
 854          */
 855         private static Module getDynamicModule(ClassLoader loader) {
 856             return dynProxyModules.computeIfAbsent(loader, (ld, clv) -> {
 857                 // create a dynamic module and setup module access
 858                 String mn = "jdk.proxy" + counter.incrementAndGet();
 859                 String pn = PROXY_PACKAGE_PREFIX + "." + mn;
 860                 Module m = Modules.defineModule(ld, mn, Collections.singleton(pn));
 861                 Modules.addReads(m, Proxy.class.getModule());
 862                 // java.base to create proxy instance
 863                 Modules.addExports(m, pn, Object.class.getModule());
 864                 return m;
 865             });
 866         }
 867     }
 868 
 869     /**
 870      * Returns a proxy instance for the specified interfaces
 871      * that dispatches method invocations to the specified invocation
 872      * handler.
 873      * <p>
 874      * <a name="restrictions">{@code IllegalArgumentException} will be thrown
 875      * if any of the following restrictions is violated:</a>
 876      * <ul>
 877      * <li>All of {@code Class} objects in the given {@code interfaces} array
 878      * must represent interfaces, not classes or primitive types.
 879      *
 880      * <li>No two elements in the {@code interfaces} array may


 947      *          <li> any of the given proxy interfaces is non-public and the
 948      *               caller class is not in the same {@linkplain Package runtime package}
 949      *               as the non-public interface and the invocation of
 950      *               {@link SecurityManager#checkPermission s.checkPermission} with
 951      *               {@code ReflectPermission("newProxyInPackage.{package name}")}
 952      *               permission denies access.</li>
 953      *          </ul>
 954      * @throws  NullPointerException if the {@code interfaces} array
 955      *          argument or any of its elements are {@code null}, or
 956      *          if the invocation handler, {@code h}, is
 957      *          {@code null}
 958      *
 959      * @see <a href="#membership">Package and Module Membership of Proxy Class</a>
 960      */
 961     @CallerSensitive
 962     public static Object newProxyInstance(ClassLoader loader,
 963                                           Class<?>[] interfaces,
 964                                           InvocationHandler h) {
 965         Objects.requireNonNull(h);
 966 
 967         final Class<?> caller = System.getSecurityManager() == null
 968                                     ? null
 969                                     : Reflection.getCallerClass();



 970 
 971         /*
 972          * Look up or generate the designated proxy class and its constructor.
 973          */
 974         Constructor<?> cons = getProxyConstructor(caller, loader, interfaces);
 975 
 976         return newProxyInstance(caller, cons, h);
 977     }
 978 
 979     private static Object newProxyInstance(Class<?> caller, // null if no SecurityManager
 980                                            Constructor<?> cons,
 981                                            InvocationHandler h) {
 982         /*
 983          * Invoke its constructor with the designated invocation handler.
 984          */
 985         try {
 986             if (caller != null) {
 987                 checkNewProxyPermission(caller, cons.getDeclaringClass());

 988             }
 989 







 990             return cons.newInstance(new Object[]{h});
 991         } catch (IllegalAccessException | InstantiationException e) {
 992             throw new InternalError(e.toString(), e);
 993         } catch (InvocationTargetException e) {
 994             Throwable t = e.getCause();
 995             if (t instanceof RuntimeException) {
 996                 throw (RuntimeException) t;
 997             } else {
 998                 throw new InternalError(t.toString(), t);
 999             }
1000         }
1001     }
1002 
1003     private static void checkNewProxyPermission(Class<?> caller, Class<?> proxyClass) {
1004         SecurityManager sm = System.getSecurityManager();
1005         if (sm != null) {
1006             if (ReflectUtil.isNonPublicProxyClass(proxyClass)) {
1007                 ClassLoader ccl = caller.getClassLoader();
1008                 ClassLoader pcl = proxyClass.getClassLoader();
1009 
1010                 // do permission check if the caller is in a different runtime package
1011                 // of the proxy class


1026      * Returns the class loader for the given module.
1027      */
1028     private static ClassLoader getLoader(Module m) {
1029         PrivilegedAction<ClassLoader> pa = m::getClassLoader;
1030         return AccessController.doPrivileged(pa);
1031     }
1032 
1033     /**
1034      * Returns true if the given class is a proxy class.
1035      *
1036      * @implNote The reliability of this method is important for the ability
1037      * to use it to make security decisions, so its implementation should
1038      * not just test if the class in question extends {@code Proxy}.
1039      *
1040      * @param   cl the class to test
1041      * @return  {@code true} if the class is a proxy class and
1042      *          {@code false} otherwise
1043      * @throws  NullPointerException if {@code cl} is {@code null}
1044      */
1045     public static boolean isProxyClass(Class<?> cl) {
1046         return Proxy.class.isAssignableFrom(cl) && ProxyBuilder.isProxyClass(cl);
1047     }
1048 
1049     /**
1050      * Returns the invocation handler for the specified proxy instance.
1051      *
1052      * @param   proxy the proxy instance to return the invocation handler for
1053      * @return  the invocation handler for the proxy instance
1054      * @throws  IllegalArgumentException if the argument is not a
1055      *          proxy instance
1056      * @throws  SecurityException if a security manager, <em>s</em>, is present
1057      *          and the caller's class loader is not the same as or an
1058      *          ancestor of the class loader for the invocation handler
1059      *          and invocation of {@link SecurityManager#checkPackageAccess
1060      *          s.checkPackageAccess()} denies access to the invocation
1061      *          handler's class.
1062      */
1063     @CallerSensitive
1064     public static InvocationHandler getInvocationHandler(Object proxy)
1065         throws IllegalArgumentException
1066     {


< prev index next >