changeset 5600:1b00d5677ee4

Merge
author ewendeli
date Mon, 28 Jan 2013 23:31:04 +0100
parents 8eb180a284b0 9641d2b88d59
children 044ea56a339d
files
diffstat 2 files changed, 24 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/lang/invoke/MethodHandleNatives.java	Tue Jan 15 18:57:42 2013 -0800
+++ b/src/share/classes/java/lang/invoke/MethodHandleNatives.java	Mon Jan 28 23:31:04 2013 +0100
@@ -507,6 +507,8 @@
         case "getProxyClass":
         case "newProxyInstance":
             return defc == java.lang.reflect.Proxy.class;
+        case "asInterfaceInstance":
+            return defc == java.lang.invoke.MethodHandleProxies.class;
         case "getBundle":
         case "clearCache":
             return defc == java.util.ResourceBundle.class;
--- a/src/share/classes/java/lang/invoke/MethodHandleProxies.java	Tue Jan 15 18:57:42 2013 -0800
+++ b/src/share/classes/java/lang/invoke/MethodHandleProxies.java	Mon Jan 28 23:31:04 2013 +0100
@@ -141,12 +141,15 @@
     <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 MethodHandle mh;
+        if (System.getSecurityManager() != null) {
             final int CALLER_FRAME = 2; // 0: Reflection, 1: asInterfaceInstance, 2: caller
             final Class<?> caller = Reflection.getCallerClass(CALLER_FRAME);
-            final ClassLoader ccl = caller.getClassLoader();
+            final ClassLoader ccl = (caller != null) ? caller.getClassLoader() : null;
             ReflectUtil.checkProxyPackageAccess(ccl, intfc);
+            mh = maybeBindCaller(target, caller);
+        } else {
+            mh = target;
         }
         ClassLoader proxyLoader = intfc.getClassLoader();
         if (proxyLoader == null) {
@@ -160,7 +163,7 @@
         for (int i = 0; i < methods.length; i++) {
             Method sm = methods[i];
             MethodType smMT = MethodType.methodType(sm.getReturnType(), sm.getParameterTypes());
-            MethodHandle checkTarget = target.asType(smMT);  // make throw WMT
+            MethodHandle checkTarget = mh.asType(smMT);  // make throw WMT
             checkTarget = checkTarget.asType(checkTarget.type().changeReturnType(Object.class));
             vaTargets[i] = checkTarget.asSpreader(Object[].class, smMT.parameterCount());
         }
@@ -183,8 +186,8 @@
                 }
             };
 
-        Object proxy;
-        if (smgr != null) {
+        final Object proxy;
+        if (System.getSecurityManager() != null) {
             // sun.invoke.WrapperInstance is a restricted interface not accessible
             // by any non-null class loader.
             final ClassLoader loader = proxyLoader;
@@ -204,6 +207,19 @@
         return intfc.cast(proxy);
     }
 
+    private static MethodHandle maybeBindCaller(MethodHandle target, Class<?> hostClass) {
+        if (hostClass == null || hostClass.getClassLoader() == null)
+            return target;
+
+        MethodHandle cbmh = MethodHandleImpl.bindCaller(target, hostClass);
+        if (target.isVarargsCollector()) {
+            MethodType type = cbmh.type();
+            int arity = type.parameterCount();
+            return cbmh.asVarargsCollector(type.parameterType(arity-1));
+        }
+        return cbmh;
+    }
+
     /**
      * Determines if the given object was produced by a call to {@link #asInterfaceInstance asInterfaceInstance}.
      * @param x any reference