10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.reflect;
27
28 import java.lang.ref.Reference;
29 import java.lang.ref.WeakReference;
30 import java.util.Arrays;
31 import java.util.Collections;
32 import java.util.HashMap;
33 import java.util.HashSet;
34 import java.util.Map;
35 import java.util.Set;
36 import java.util.List;
37 import java.util.WeakHashMap;
38 import sun.misc.ProxyGenerator;
39
40 /**
41 * {@code Proxy} provides static methods for creating dynamic proxy
42 * classes and instances, and it is also the superclass of all
43 * dynamic proxy classes created by those methods.
44 *
45 * <p>To create a proxy for some interface {@code Foo}:
46 * <pre>
47 * InvocationHandler handler = new MyInvocationHandler(...);
48 * Class proxyClass = Proxy.getProxyClass(
49 * Foo.class.getClassLoader(), new Class[] { Foo.class });
50 * Foo f = (Foo) proxyClass.
51 * getConstructor(new Class[] { InvocationHandler.class }).
52 * newInstance(new Object[] { handler });
53 * </pre>
54 * or more simply:
55 * <pre>
56 * Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
57 * new Class[] { Foo.class },
58 * handler);
248 /**
249 * the invocation handler for this proxy instance.
250 * @serial
251 */
252 protected InvocationHandler h;
253
254 /**
255 * Prohibits instantiation.
256 */
257 private Proxy() {
258 }
259
260 /**
261 * Constructs a new {@code Proxy} instance from a subclass
262 * (typically, a dynamic proxy class) with the specified value
263 * for its invocation handler.
264 *
265 * @param h the invocation handler for this proxy instance
266 */
267 protected Proxy(InvocationHandler h) {
268 this.h = h;
269 }
270
271 /**
272 * Returns the {@code java.lang.Class} object for a proxy class
273 * given a class loader and an array of interfaces. The proxy class
274 * will be defined by the specified class loader and will implement
275 * all of the supplied interfaces. If a proxy class for the same
276 * permutation of interfaces has already been defined by the class
277 * loader, then the existing proxy class will be returned; otherwise,
278 * a proxy class for those interfaces will be generated dynamically
279 * and defined by the class loader.
280 *
281 * <p>There are several restrictions on the parameters that may be
282 * passed to {@code Proxy.getProxyClass}:
283 *
284 * <ul>
285 * <li>All of the {@code Class} objects in the
286 * {@code interfaces} array must represent interfaces, not
287 * classes or primitive types.
288 *
289 * <li>No two elements in the {@code interfaces} array may
290 * refer to identical {@code Class} objects.
329 * <p>Note that the order of the specified proxy interfaces is
330 * significant: two requests for a proxy class with the same combination
331 * of interfaces but in a different order will result in two distinct
332 * proxy classes.
333 *
334 * @param loader the class loader to define the proxy class
335 * @param interfaces the list of interfaces for the proxy class
336 * to implement
337 * @return a proxy class that is defined in the specified class loader
338 * and that implements the specified interfaces
339 * @throws IllegalArgumentException if any of the restrictions on the
340 * parameters that may be passed to {@code getProxyClass}
341 * are violated
342 * @throws NullPointerException if the {@code interfaces} array
343 * argument or any of its elements are {@code null}
344 */
345 public static Class<?> getProxyClass(ClassLoader loader,
346 Class<?>... interfaces)
347 throws IllegalArgumentException
348 {
349 if (interfaces.length > 65535) {
350 throw new IllegalArgumentException("interface limit exceeded");
351 }
352
353 Class<?> proxyClass = null;
354
355 /* collect interface names to use as key for proxy class cache */
356 String[] interfaceNames = new String[interfaces.length];
357
358 // for detecting duplicates
359 Set<Class<?>> interfaceSet = new HashSet<>();
360
361 for (int i = 0; i < interfaces.length; i++) {
362 /*
363 * Verify that the class loader resolves the name of this
364 * interface to the same Class object.
365 */
366 String interfaceName = interfaces[i].getName();
367 Class<?> interfaceClass = null;
368 try {
480 /*
481 * Record the package of a non-public proxy interface so that the
482 * proxy class will be defined in the same package. Verify that
483 * all non-public proxy interfaces are in the same package.
484 */
485 for (int i = 0; i < interfaces.length; i++) {
486 int flags = interfaces[i].getModifiers();
487 if (!Modifier.isPublic(flags)) {
488 String name = interfaces[i].getName();
489 int n = name.lastIndexOf('.');
490 String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
491 if (proxyPkg == null) {
492 proxyPkg = pkg;
493 } else if (!pkg.equals(proxyPkg)) {
494 throw new IllegalArgumentException(
495 "non-public interfaces from different packages");
496 }
497 }
498 }
499
500 if (proxyPkg == null) { // if no non-public proxy interfaces,
501 proxyPkg = ""; // use the unnamed package
502 }
503
504 {
505 /*
506 * Choose a name for the proxy class to generate.
507 */
508 long num;
509 synchronized (nextUniqueNumberLock) {
510 num = nextUniqueNumber++;
511 }
512 String proxyName = proxyPkg + proxyClassNamePrefix + num;
513 /*
514 * Verify that the class loader hasn't already
515 * defined a class with the chosen name.
516 */
517
518 /*
519 * Generate the specified proxy class.
520 */
521 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
581 * @throws IllegalArgumentException if any of the restrictions on the
582 * parameters that may be passed to {@code getProxyClass}
583 * are violated
584 * @throws NullPointerException if the {@code interfaces} array
585 * argument or any of its elements are {@code null}, or
586 * if the invocation handler, {@code h}, is
587 * {@code null}
588 */
589 public static Object newProxyInstance(ClassLoader loader,
590 Class<?>[] interfaces,
591 InvocationHandler h)
592 throws IllegalArgumentException
593 {
594 if (h == null) {
595 throw new NullPointerException();
596 }
597
598 /*
599 * Look up or generate the designated proxy class.
600 */
601 Class<?> cl = getProxyClass(loader, interfaces);
602
603 /*
604 * Invoke its constructor with the designated invocation handler.
605 */
606 try {
607 Constructor cons = cl.getConstructor(constructorParams);
608 return cons.newInstance(new Object[] { h });
609 } catch (NoSuchMethodException e) {
610 throw new InternalError(e.toString());
611 } catch (IllegalAccessException e) {
612 throw new InternalError(e.toString());
613 } catch (InstantiationException e) {
614 throw new InternalError(e.toString());
615 } catch (InvocationTargetException e) {
616 throw new InternalError(e.toString());
617 }
618 }
619
620 /**
621 * Returns true if and only if the specified class was dynamically
622 * generated to be a proxy class using the {@code getProxyClass}
623 * method or the {@code newProxyInstance} method.
624 *
625 * <p>The reliability of this method is important for the ability
626 * to use it to make security decisions, so its implementation should
627 * not just test if the class in question extends {@code Proxy}.
628 *
629 * @param cl the class to test
630 * @return {@code true} if the class is a proxy class and
631 * {@code false} otherwise
632 * @throws NullPointerException if {@code cl} is {@code null}
633 */
634 public static boolean isProxyClass(Class<?> cl) {
635 if (cl == null) {
636 throw new NullPointerException();
|
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.lang.reflect;
27
28 import java.lang.ref.Reference;
29 import java.lang.ref.WeakReference;
30 import java.security.AccessController;
31 import java.security.Permission;
32 import java.security.PrivilegedAction;
33 import java.util.Arrays;
34 import java.util.Collections;
35 import java.util.HashMap;
36 import java.util.HashSet;
37 import java.util.Map;
38 import java.util.Set;
39 import java.util.List;
40 import java.util.WeakHashMap;
41 import sun.misc.ProxyGenerator;
42 import sun.reflect.Reflection;
43 import sun.reflect.misc.ReflectUtil;
44 import sun.security.util.SecurityConstants;
45
46 /**
47 * {@code Proxy} provides static methods for creating dynamic proxy
48 * classes and instances, and it is also the superclass of all
49 * dynamic proxy classes created by those methods.
50 *
51 * <p>To create a proxy for some interface {@code Foo}:
52 * <pre>
53 * InvocationHandler handler = new MyInvocationHandler(...);
54 * Class proxyClass = Proxy.getProxyClass(
55 * Foo.class.getClassLoader(), new Class[] { Foo.class });
56 * Foo f = (Foo) proxyClass.
57 * getConstructor(new Class[] { InvocationHandler.class }).
58 * newInstance(new Object[] { handler });
59 * </pre>
60 * or more simply:
61 * <pre>
62 * Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
63 * new Class[] { Foo.class },
64 * handler);
254 /**
255 * the invocation handler for this proxy instance.
256 * @serial
257 */
258 protected InvocationHandler h;
259
260 /**
261 * Prohibits instantiation.
262 */
263 private Proxy() {
264 }
265
266 /**
267 * Constructs a new {@code Proxy} instance from a subclass
268 * (typically, a dynamic proxy class) with the specified value
269 * for its invocation handler.
270 *
271 * @param h the invocation handler for this proxy instance
272 */
273 protected Proxy(InvocationHandler h) {
274 doNewInstanceCheck();
275 this.h = h;
276 }
277
278 private static class ProxyAccessHelper {
279 // The permission is implementation specific.
280 static final Permission PROXY_PERMISSION =
281 new ReflectPermission("proxyConstructorNewInstance");
282 // These system properties are defined to provide a short-term
283 // workaround if customers need to disable the new security checks.
284 static final boolean allowNewInstance;
285 static final boolean allowNullLoader;
286 static {
287 allowNewInstance = getBooleanProperty("sun.reflect.proxy.allowsNewInstance");
288 allowNullLoader = getBooleanProperty("sun.reflect.proxy.allowsNullLoader");
289 }
290
291 private static boolean getBooleanProperty(final String key) {
292 String s = AccessController.doPrivileged(new PrivilegedAction<String>() {
293 public String run() {
294 return System.getProperty(key);
295 }
296 });
297 return Boolean.valueOf(s);
298 }
299
300 static boolean needsNewInstanceCheck(Class<?> proxyClass) {
301 if (!Proxy.isProxyClass(proxyClass) || allowNewInstance) {
302 return false;
303 }
304
305 if (proxyClass.getName().startsWith(ReflectUtil.PROXY_PACKAGE + ".")) {
306 // all proxy interfaces are public
307 return false;
308 }
309 for (Class<?> intf : proxyClass.getInterfaces()) {
310 if (!Modifier.isPublic(intf.getModifiers())) {
311 return true;
312 }
313 }
314 return false;
315 }
316 }
317
318 /*
319 * Access check on a proxy class that implements any non-public interface.
320 *
321 * @throws SecurityException if a security manager exists, and
322 * the caller does not have the permission.
323 */
324 private void doNewInstanceCheck() {
325 SecurityManager sm = System.getSecurityManager();
326 Class<?> proxyClass = this.getClass();
327 if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(proxyClass)) {
328 try {
329 sm.checkPermission(ProxyAccessHelper.PROXY_PERMISSION);
330 } catch (SecurityException e) {
331 throw new SecurityException("Not allowed to construct a Proxy "
332 + "instance that implements a non-public interface", e);
333 }
334 }
335 }
336
337 /**
338 * Returns the {@code java.lang.Class} object for a proxy class
339 * given a class loader and an array of interfaces. The proxy class
340 * will be defined by the specified class loader and will implement
341 * all of the supplied interfaces. If a proxy class for the same
342 * permutation of interfaces has already been defined by the class
343 * loader, then the existing proxy class will be returned; otherwise,
344 * a proxy class for those interfaces will be generated dynamically
345 * and defined by the class loader.
346 *
347 * <p>There are several restrictions on the parameters that may be
348 * passed to {@code Proxy.getProxyClass}:
349 *
350 * <ul>
351 * <li>All of the {@code Class} objects in the
352 * {@code interfaces} array must represent interfaces, not
353 * classes or primitive types.
354 *
355 * <li>No two elements in the {@code interfaces} array may
356 * refer to identical {@code Class} objects.
395 * <p>Note that the order of the specified proxy interfaces is
396 * significant: two requests for a proxy class with the same combination
397 * of interfaces but in a different order will result in two distinct
398 * proxy classes.
399 *
400 * @param loader the class loader to define the proxy class
401 * @param interfaces the list of interfaces for the proxy class
402 * to implement
403 * @return a proxy class that is defined in the specified class loader
404 * and that implements the specified interfaces
405 * @throws IllegalArgumentException if any of the restrictions on the
406 * parameters that may be passed to {@code getProxyClass}
407 * are violated
408 * @throws NullPointerException if the {@code interfaces} array
409 * argument or any of its elements are {@code null}
410 */
411 public static Class<?> getProxyClass(ClassLoader loader,
412 Class<?>... interfaces)
413 throws IllegalArgumentException
414 {
415 return getProxyClass0(loader, interfaces); // stack walk magic: do not refactor
416 }
417
418 private static void checkProxyLoader(ClassLoader ccl,
419 ClassLoader loader)
420 {
421 SecurityManager sm = System.getSecurityManager();
422 if (sm != null) {
423 if (loader == null && ccl != null) {
424 if (!ProxyAccessHelper.allowNullLoader) {
425 sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
426 }
427 }
428 }
429 }
430
431 /*
432 * Generate a proxy class (caller-sensitive).
433 *
434 * To define a proxy class, it performs the access checks as in
435 * Class.forName (VM will invoke ClassLoader.checkPackageAccess):
436 * 1. "getClassLoader" permission check if loader == null
437 * 2. checkPackageAccess on the interfaces it implements
438 *
439 * To get a constructor and new instance of a proxy class, it performs
440 * the package access check on the interfaces it implements
441 * as in Class.getConstructor.
442 *
443 * If an interface is non-public, the proxy class must be defined by
444 * the defining loader of the interface. If the caller's class loader
445 * is not the same as the defining loader of the interface, the VM
446 * will throw IllegalAccessError when the generated proxy class is
447 * being defined via the defineClass0 method.
448 */
449 private static Class<?> getProxyClass0(ClassLoader loader,
450 Class<?>... interfaces) {
451 SecurityManager sm = System.getSecurityManager();
452 if (sm != null) {
453 final int CALLER_FRAME = 3; // 0: Reflection, 1: getProxyClass0 2: Proxy 3: caller
454 final Class<?> caller = Reflection.getCallerClass(CALLER_FRAME);
455 final ClassLoader ccl = caller.getClassLoader();
456 checkProxyLoader(ccl, loader);
457 ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
458 }
459
460 if (interfaces.length > 65535) {
461 throw new IllegalArgumentException("interface limit exceeded");
462 }
463
464 Class<?> proxyClass = null;
465
466 /* collect interface names to use as key for proxy class cache */
467 String[] interfaceNames = new String[interfaces.length];
468
469 // for detecting duplicates
470 Set<Class<?>> interfaceSet = new HashSet<>();
471
472 for (int i = 0; i < interfaces.length; i++) {
473 /*
474 * Verify that the class loader resolves the name of this
475 * interface to the same Class object.
476 */
477 String interfaceName = interfaces[i].getName();
478 Class<?> interfaceClass = null;
479 try {
591 /*
592 * Record the package of a non-public proxy interface so that the
593 * proxy class will be defined in the same package. Verify that
594 * all non-public proxy interfaces are in the same package.
595 */
596 for (int i = 0; i < interfaces.length; i++) {
597 int flags = interfaces[i].getModifiers();
598 if (!Modifier.isPublic(flags)) {
599 String name = interfaces[i].getName();
600 int n = name.lastIndexOf('.');
601 String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
602 if (proxyPkg == null) {
603 proxyPkg = pkg;
604 } else if (!pkg.equals(proxyPkg)) {
605 throw new IllegalArgumentException(
606 "non-public interfaces from different packages");
607 }
608 }
609 }
610
611 if (proxyPkg == null) {
612 // if no non-public proxy interfaces, use sun.proxy package
613 proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
614 }
615
616 {
617 /*
618 * Choose a name for the proxy class to generate.
619 */
620 long num;
621 synchronized (nextUniqueNumberLock) {
622 num = nextUniqueNumber++;
623 }
624 String proxyName = proxyPkg + proxyClassNamePrefix + num;
625 /*
626 * Verify that the class loader hasn't already
627 * defined a class with the chosen name.
628 */
629
630 /*
631 * Generate the specified proxy class.
632 */
633 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
693 * @throws IllegalArgumentException if any of the restrictions on the
694 * parameters that may be passed to {@code getProxyClass}
695 * are violated
696 * @throws NullPointerException if the {@code interfaces} array
697 * argument or any of its elements are {@code null}, or
698 * if the invocation handler, {@code h}, is
699 * {@code null}
700 */
701 public static Object newProxyInstance(ClassLoader loader,
702 Class<?>[] interfaces,
703 InvocationHandler h)
704 throws IllegalArgumentException
705 {
706 if (h == null) {
707 throw new NullPointerException();
708 }
709
710 /*
711 * Look up or generate the designated proxy class.
712 */
713 Class<?> cl = getProxyClass0(loader, interfaces); // stack walk magic: do not refactor
714
715 /*
716 * Invoke its constructor with the designated invocation handler.
717 */
718 try {
719 final Constructor<?> cons = cl.getConstructor(constructorParams);
720 final InvocationHandler ih = h;
721 SecurityManager sm = System.getSecurityManager();
722 if (sm != null && ProxyAccessHelper.needsNewInstanceCheck(cl)) {
723 // create proxy instance with doPrivilege as the proxy class may
724 // implement non-public interfaces that requires a special permission
725 return AccessController.doPrivileged(new PrivilegedAction<Object>() {
726 public Object run() {
727 return newInstance(cons, ih);
728 }
729 });
730 } else {
731 return newInstance(cons, ih);
732 }
733 } catch (NoSuchMethodException e) {
734 throw new InternalError(e.toString());
735 }
736 }
737
738 private static Object newInstance(Constructor<?> cons, InvocationHandler h) {
739 try {
740 return cons.newInstance(new Object[] {h} );
741 } catch (IllegalAccessException | InstantiationException e) {
742 throw new InternalError(e.toString());
743 } catch (InvocationTargetException e) {
744 Throwable t = e.getCause();
745 if (t instanceof RuntimeException) {
746 throw (RuntimeException) t;
747 } else {
748 throw new InternalError(t.toString());
749 }
750 }
751 }
752
753 /**
754 * Returns true if and only if the specified class was dynamically
755 * generated to be a proxy class using the {@code getProxyClass}
756 * method or the {@code newProxyInstance} method.
757 *
758 * <p>The reliability of this method is important for the ability
759 * to use it to make security decisions, so its implementation should
760 * not just test if the class in question extends {@code Proxy}.
761 *
762 * @param cl the class to test
763 * @return {@code true} if the class is a proxy class and
764 * {@code false} otherwise
765 * @throws NullPointerException if {@code cl} is {@code null}
766 */
767 public static boolean isProxyClass(Class<?> cl) {
768 if (cl == null) {
769 throw new NullPointerException();
|