1.1 --- a/src/share/classes/java/dyn/MethodHandles.java Mon May 11 21:09:58 2009 -0700
1.2 +++ b/src/share/classes/java/dyn/MethodHandles.java Tue May 12 13:54:22 2009 -0700
1.3 @@ -145,27 +145,30 @@
1.4 this.lookupClass = lookupClass;
1.5 }
1.6
1.7 + private static final Class<?> PUBLIC_ONLY = sun.dyn.empty.Empty.class;
1.8 +
1.9 /** Version of lookup which is trusted minimally.
1.10 * It can only be used to create method handles to
1.11 * publicly accessible members.
1.12 */
1.13 - public static final Lookup PUBLIC_LOOKUP = new Lookup(null);
1.14 + public static final Lookup PUBLIC_LOOKUP = new Lookup(PUBLIC_ONLY);
1.15
1.16 /** Package-private version of lookup which is trusted. */
1.17 - static final Lookup IMPL_LOOKUP = new Lookup(Access.class);
1.18 + static final Lookup IMPL_LOOKUP = new Lookup(null);
1.19 static { MethodHandleImpl.initLookup(IMPL_TOKEN, IMPL_LOOKUP); }
1.20
1.21 private static void checkUnprivilegedlookupClass(Class<?> lookupClass) {
1.22 - if (lookupClass == null ||
1.23 - lookupClass == Access.class ||
1.24 - lookupClass.getName().startsWith("java.dyn."))
1.25 + String name = lookupClass.getName();
1.26 + if (name.startsWith("java.dyn.") || name.startsWith("sun.dyn."))
1.27 throw newIllegalArgumentException("illegal lookupClass: "+lookupClass);
1.28 }
1.29
1.30 @Override
1.31 public String toString() {
1.32 + if (lookupClass == PUBLIC_ONLY)
1.33 + return "public";
1.34 if (lookupClass == null)
1.35 - return "public";
1.36 + return "privileged";
1.37 return lookupClass.getName();
1.38 }
1.39
1.40 @@ -205,6 +208,13 @@
1.41 * with the receiver type ({@code defc}) prepended.
1.42 * The method and all its argument types must be accessible to the lookup class.
1.43 * <p>
1.44 + * (<em>BUG NOTE:</em> The type {@code Object} may be prepended instead
1.45 + * of the receiver type, if the receiver type is not on the boot class path.
1.46 + * This is due to a temporary JVM limitation, in which MethodHandle
1.47 + * claims to be unable to access such classes. To work around this
1.48 + * bug, use {@code convertArguments} to normalize the type of the leading
1.49 + * argument to a type on the boot class path, such as {@code Object}.)
1.50 + * <p>
1.51 * When called, the handle will treat the first argument as a receiver
1.52 * and dispatch on the receiver's type to determine which method
1.53 * implementation to enter.
1.54 @@ -253,8 +263,7 @@
1.55 MemberName method = IMPL_NAMES.resolveOrFail(new MemberName(defc, name, type), false, specialCaller);
1.56 checkStatic(false, method, lookupClass);
1.57 if (name.equals("<init>")) {
1.58 - if (defc != specialCaller)
1.59 - throw newNoAccessException("constructor must be local to lookup class", method, lookupClass);
1.60 + throw newNoAccessException("cannot directly invoke a constructor", method, null);
1.61 } else if (defc.isInterface() || !defc.isAssignableFrom(specialCaller)) {
1.62 throw newNoAccessException("method must be in a superclass of lookup class", method, lookupClass);
1.63 }
2.1 --- a/src/share/classes/sun/dyn/DirectMethodHandle.java Mon May 11 21:09:58 2009 -0700
2.2 +++ b/src/share/classes/sun/dyn/DirectMethodHandle.java Tue May 12 13:54:22 2009 -0700
2.3 @@ -45,8 +45,6 @@
2.4 if (!m.isResolved())
2.5 throw new InternalError();
2.6
2.7 - // Null check and replace privilege token (as passed to JVM) with null.
2.8 - if (lookupClass.equals(Access.class)) lookupClass = null;
2.9 MethodHandleNatives.init(this, (Object) m, doDispatch, lookupClass);
2.10 }
2.11
3.1 --- a/src/share/classes/sun/dyn/MemberName.java Mon May 11 21:09:58 2009 -0700
3.2 +++ b/src/share/classes/sun/dyn/MemberName.java Tue May 12 13:54:22 2009 -0700
3.3 @@ -450,7 +450,7 @@
3.4 for (;;) {
3.5 int bufCount = MethodHandleNatives.getMembers(defc,
3.6 matchName, matchSig, matchFlags,
3.7 - MethodHandleNatives.asNativeCaller(lookupClass),
3.8 + lookupClass,
3.9 totalCount, buf);
3.10 if (bufCount <= buf.length) {
3.11 if (bufCount >= 0)
3.12 @@ -487,14 +487,13 @@
3.13 return result;
3.14 }
3.15 boolean resolveInPlace(MemberName m, boolean searchSupers, Class<?> lookupClass) {
3.16 - Class<?> caller = MethodHandleNatives.asNativeCaller(lookupClass);
3.17 - MethodHandleNatives.resolve(m, caller);
3.18 + MethodHandleNatives.resolve(m, lookupClass);
3.19 if (m.isResolved()) return true;
3.20 int matchFlags = m.flags | (searchSupers ? SEARCH_ALL_SUPERS : 0);
3.21 String matchSig = m.getSignature();
3.22 MemberName[] buf = { m };
3.23 int n = MethodHandleNatives.getMembers(m.getDeclaringClass(),
3.24 - m.getName(), matchSig, matchFlags, caller, 0, buf);
3.25 + m.getName(), matchSig, matchFlags, lookupClass, 0, buf);
3.26 if (n != 1) return false;
3.27 return m.isResolved();
3.28 }
4.1 --- a/src/share/classes/sun/dyn/MethodHandleImpl.java Mon May 11 21:09:58 2009 -0700
4.2 +++ b/src/share/classes/sun/dyn/MethodHandleImpl.java Tue May 12 13:54:22 2009 -0700
4.3 @@ -95,7 +95,7 @@
4.4
4.5 public static void initLookup(Access token, Lookup lookup) {
4.6 Access.check(token);
4.7 - if (IMPL_LOOKUP_INIT != null || lookup.lookupClass() != Access.class)
4.8 + if (IMPL_LOOKUP_INIT != null || lookup.lookupClass() != null)
4.9 throw new InternalError();
4.10 IMPL_LOOKUP_INIT = lookup;
4.11 }
4.12 @@ -144,19 +144,28 @@
4.13 boolean doDispatch, Class<?> lookupClass) {
4.14 Access.check(token); // only trusted calls
4.15 MethodType mtype = method.getMethodType();
4.16 + MethodType rtype = mtype;
4.17 if (method.isStatic()) {
4.18 doDispatch = false;
4.19 } else {
4.20 // adjust the advertised receiver type to be exactly the one requested
4.21 // (in the case of invokespecial, this will be the calling class)
4.22 - mtype = mtype.insertParameterType(0, method.getDeclaringClass());
4.23 + Class<?> recvType = method.getDeclaringClass();
4.24 + mtype = mtype.insertParameterType(0, recvType);
4.25 if (method.isConstructor())
4.26 doDispatch = true;
4.27 + // FIXME: JVM has trouble building MH.invoke sites for
4.28 + // classes off the boot class path
4.29 + rtype = mtype;
4.30 + if (recvType.getClassLoader() != null)
4.31 + rtype = rtype.changeParameterType(0, Object.class);
4.32 }
4.33 DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass);
4.34 if (!mh.isValid())
4.35 throw newNoAccessException(method, lookupClass);
4.36 - return mh;
4.37 + MethodHandle rmh = AdapterMethodHandle.makePairwiseConvert(token, rtype, mh);
4.38 + if (rmh == null) throw new InternalError();
4.39 + return rmh;
4.40 }
4.41
4.42 public static
4.43 @@ -189,6 +198,15 @@
4.44 MethodHandle bindReceiver(Access token,
4.45 MethodHandle target, Object receiver) {
4.46 Access.check(token);
4.47 + if (target instanceof AdapterMethodHandle) {
4.48 + Object info = MethodHandleNatives.getTargetInfo(target);
4.49 + if (info instanceof DirectMethodHandle) {
4.50 + DirectMethodHandle dmh = (DirectMethodHandle) info;
4.51 + if (receiver == null ||
4.52 + dmh.type().parameterType(0).isAssignableFrom(receiver.getClass()))
4.53 + target = dmh;
4.54 + }
4.55 + }
4.56 if (target instanceof DirectMethodHandle)
4.57 return new BoundMethodHandle((DirectMethodHandle)target, receiver, 0);
4.58 return null; // let caller try something else
5.1 --- a/src/share/classes/sun/dyn/MethodHandleNatives.java Mon May 11 21:09:58 2009 -0700
5.2 +++ b/src/share/classes/sun/dyn/MethodHandleNatives.java Tue May 12 13:54:22 2009 -0700
5.3 @@ -47,14 +47,6 @@
5.4 static native int getMembers(Class<?> defc, String matchName, String matchSig,
5.5 int matchFlags, Class<?> caller, int skip, MemberName[] results);
5.6
5.7 - static Class<?> asNativeCaller(Class<?> lookupClass) {
5.8 - if (lookupClass == null) // means "public only, non-privileged"
5.9 - return sun.dyn.empty.Empty.class;
5.10 - if (lookupClass == Access.class) // means "internal, privileged"
5.11 - return null; // to the JVM, null means completely privileged
5.12 - return lookupClass;
5.13 - }
5.14 -
5.15 /// MethodHandle support
5.16
5.17 /** Initialize the method handle to adapt the call. */
6.1 --- a/src/share/classes/sun/dyn/util/VerifyAccess.java Mon May 11 21:09:58 2009 -0700
6.2 +++ b/src/share/classes/sun/dyn/util/VerifyAccess.java Tue May 12 13:54:22 2009 -0700
6.3 @@ -95,7 +95,7 @@
6.4 public static boolean isSamePackage(Class<?> class1, Class<?> class2) {
6.5 if (class1 == class2)
6.6 return true;
6.7 - if (loadersAreRelated(class1.getClassLoader(), class2.getClassLoader()))
6.8 + if (!loadersAreRelated(class1.getClassLoader(), class2.getClassLoader()))
6.9 return false;
6.10 String name1 = class1.getName(), name2 = class2.getName();
6.11 int dot = name1.lastIndexOf('.');
6.12 @@ -159,7 +159,7 @@
6.13 */
6.14 public static void checkBootstrapPrivilege(Class requestingClass, Class subjectClass,
6.15 String permissionName) {
6.16 - if (requestingClass == Access.class) return;
6.17 + if (requestingClass == null) return;
6.18 if (requestingClass == subjectClass) return;
6.19 SecurityManager security = System.getSecurityManager();
6.20 if (security == null) return; // open season