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 {
|