jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java

Print this page
rev 5725 : Merge

@@ -24,12 +24,16 @@
  */
 
 package java.lang.invoke;
 
 import java.lang.reflect.*;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import sun.invoke.WrapperInstance;
 import java.util.ArrayList;
+import sun.reflect.Reflection;
+import sun.reflect.misc.ReflectUtil;
 
 /**
  * This class consists exclusively of static methods that help adapt
  * method handles to other JVM types, such as interfaces.
  */

@@ -135,10 +139,22 @@
     //
     public static
     <T> T asInterfaceInstance(final Class<T> intfc, final MethodHandle target) {
         if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers()))
             throw new IllegalArgumentException("not a public interface: "+intfc.getName());
+        SecurityManager smgr = System.getSecurityManager();
+        if (smgr != null) {
+            final int CALLER_FRAME = 2; // 0: Reflection, 1: asInterfaceInstance, 2: caller
+            final Class<?> caller = Reflection.getCallerClass(CALLER_FRAME);
+            final ClassLoader ccl = caller.getClassLoader();
+            ReflectUtil.checkProxyPackageAccess(ccl, intfc);
+        }
+        ClassLoader proxyLoader = intfc.getClassLoader();
+        if (proxyLoader == null) {
+            ClassLoader cl = Thread.currentThread().getContextClassLoader(); // avoid use of BCP
+            proxyLoader = cl != null ? cl : ClassLoader.getSystemClassLoader();
+        }
         final Method[] methods = getSingleNameMethods(intfc);
         if (methods == null)
             throw new IllegalArgumentException("not a single-method interface: "+intfc.getName());
         final MethodHandle[] vaTargets = new MethodHandle[methods.length];
         for (int i = 0; i < methods.length; i++) {

@@ -146,14 +162,11 @@
             MethodType smMT = MethodType.methodType(sm.getReturnType(), sm.getParameterTypes());
             MethodHandle checkTarget = target.asType(smMT);  // make throw WMT
             checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class));
             vaTargets[i] = checkTarget.asSpreader(Object[].class, smMT.parameterCount());
         }
-        return intfc.cast(Proxy.newProxyInstance(
-                intfc.getClassLoader(),
-                new Class<?>[]{ intfc, WrapperInstance.class },
-                new InvocationHandler() {
+        final InvocationHandler ih = new InvocationHandler() {
                     private Object getArg(String name) {
                         if ((Object)name == "getWrapperInstanceTarget")  return target;
                         if ((Object)name == "getWrapperInstanceType")    return intfc;
                         throw new AssertionError();
                     }

@@ -166,11 +179,31 @@
                             return getArg(method.getName());
                         if (isObjectMethod(method))
                             return callObjectMethod(proxy, method, args);
                         throw new InternalError("bad proxy method: "+method);
                     }
-                }));
+            };
+
+        Object proxy;
+        if (smgr != null) {
+            // sun.invoke.WrapperInstance is a restricted interface not accessible
+            // by any non-null class loader.
+            final ClassLoader loader = proxyLoader;
+            proxy = AccessController.doPrivileged(new PrivilegedAction<Object>() {
+                public Object run() {
+                    return Proxy.newProxyInstance(
+                            loader,
+                            new Class<?>[]{ intfc, WrapperInstance.class },
+                            ih);
+                }
+            });
+        } else {
+            proxy = Proxy.newProxyInstance(proxyLoader,
+                                           new Class<?>[]{ intfc, WrapperInstance.class },
+                                           ih);
+        }
+        return intfc.cast(proxy);
     }
 
     /**
      * Determines if the given object was produced by a call to {@link #asInterfaceInstance asInterfaceInstance}.
      * @param x any reference