aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormchung <none@none>2013-01-24 16:45:38 -0800
committermchung <none@none>2013-01-24 16:45:38 -0800
commitb36c3a5b26372457915c0adccc92e3b4061baeae (patch)
tree495112a8ce710a2e37dc34f419e120a272a5071b
parent0fe8bddb0fab646aedf31215b2ab43e7a4bcea66 (diff)
downloadjdk8u_jdk-b36c3a5b26372457915c0adccc92e3b4061baeae.tar.gz
8004937: Improve proxy construction
Reviewed-by: jrose, ahgross
-rw-r--r--src/share/classes/java/lang/invoke/MethodHandleNatives.java2
-rw-r--r--src/share/classes/java/lang/invoke/MethodHandleProxies.java25
2 files changed, 21 insertions, 6 deletions
diff --git a/src/share/classes/java/lang/invoke/MethodHandleNatives.java b/src/share/classes/java/lang/invoke/MethodHandleNatives.java
index fcc928a327..8f1d0c3164 100644
--- a/src/share/classes/java/lang/invoke/MethodHandleNatives.java
+++ b/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/src/share/classes/java/lang/invoke/MethodHandleProxies.java b/src/share/classes/java/lang/invoke/MethodHandleProxies.java
index b000116d87..ade1630dcf 100644
--- a/src/share/classes/java/lang/invoke/MethodHandleProxies.java
+++ b/src/share/classes/java/lang/invoke/MethodHandleProxies.java
@@ -141,12 +141,15 @@ public class MethodHandleProxies {
<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 = 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