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