From fad9c0e89cf9e887aa6f04e1055a8b6c3248e5ad Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Thu, 24 Jan 2013 16:45:38 -0800 Subject: [PATCH] 8004937: Improve proxy construction Reviewed-by: jrose, ahgross --- .../java/lang/invoke/MethodHandleNatives.java | 2 ++ .../java/lang/invoke/MethodHandleProxies.java | 25 ++++++++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java index fcc928a327d..8f1d0c3164e 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -476,6 +476,8 @@ class MethodHandleNatives { 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; diff --git a/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java b/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java index b000116d875..ade1630dcfb 100644 --- a/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleProxies.java @@ -141,12 +141,15 @@ public class MethodHandleProxies { T asInterfaceInstance(final Class 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 = ccl != null ? bindCaller(target, caller) : target; + } else { + mh = target; } ClassLoader proxyLoader = intfc.getClassLoader(); if (proxyLoader == null) { @@ -160,7 +163,7 @@ public class MethodHandleProxies { 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 @@ public class MethodHandleProxies { } }; - 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,16 @@ public class MethodHandleProxies { return intfc.cast(proxy); } + private static MethodHandle bindCaller(MethodHandle target, Class hostClass) { + 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