6939196: method handle signatures off the boot class path get linkage errors

Remove workaround from MethodHandleImpl lookup code; add JUnit regression test to MethodHandlesTest.

Reviewed-by: twisti
This commit is contained in:
John R Rose 2010-05-03 23:32:47 -07:00
parent 0d30a781cf
commit 07ee2dd259
2 changed files with 34 additions and 21 deletions

View file

@ -176,28 +176,16 @@ public abstract class MethodHandleImpl {
boolean doDispatch, Class<?> lookupClass) { boolean doDispatch, Class<?> lookupClass) {
Access.check(token); // only trusted calls Access.check(token); // only trusted calls
MethodType mtype = method.getMethodType(); MethodType mtype = method.getMethodType();
MethodType rtype = mtype;
if (!method.isStatic()) { if (!method.isStatic()) {
// adjust the advertised receiver type to be exactly the one requested // adjust the advertised receiver type to be exactly the one requested
// (in the case of invokespecial, this will be the calling class) // (in the case of invokespecial, this will be the calling class)
Class<?> recvType = method.getDeclaringClass(); Class<?> recvType = method.getDeclaringClass();
mtype = mtype.insertParameterTypes(0, recvType); mtype = mtype.insertParameterTypes(0, recvType);
// FIXME: JVM has trouble building MH.invoke sites for
// classes off the boot class path
rtype = mtype;
if (recvType.getClassLoader() != null) {
rtype = rtype.changeParameterType(0, Object.class);
}
} }
DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass); DirectMethodHandle mh = new DirectMethodHandle(mtype, method, doDispatch, lookupClass);
if (!mh.isValid()) if (!mh.isValid())
throw newNoAccessException(method, lookupClass); throw newNoAccessException(method, lookupClass);
if (rtype != mtype) { assert(mh.type() == mtype);
MethodHandle rmh = AdapterMethodHandle.makePairwiseConvert(token, rtype, mh);
if (rmh == null) throw new InternalError();
return rmh;
}
assert(mh.type() == rtype);
return mh; return mh;
} }

View file

@ -515,10 +515,6 @@ public class MethodHandlesTest {
if (!positive) return; // negative test failed as expected if (!positive) return; // negative test failed as expected
Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params); Class<?>[] paramsWithSelf = cat(array(Class[].class, (Class)defc), params);
MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf); MethodType typeWithSelf = MethodType.methodType(ret, paramsWithSelf);
if (defc.getClassLoader() != null) // detune due to 6939196
assertEquals(typeWithSelf.dropParameterTypes(0,1),
target.type().dropParameterTypes(0,1));
else // FIXME: use only this test when 6939196 is fixed
assertEquals(typeWithSelf, target.type()); assertEquals(typeWithSelf, target.type());
assertTrue(target.toString().contains(methodName)); // rough check assertTrue(target.toString().contains(methodName)); // rough check
if (!DO_MORE_CALLS && lookup != PRIVATE) return; if (!DO_MORE_CALLS && lookup != PRIVATE) return;
@ -714,10 +710,6 @@ public class MethodHandlesTest {
if (isStatic) { if (isStatic) {
assertEquals(typeMaybeWithSelf, target.type()); assertEquals(typeMaybeWithSelf, target.type());
} else { } else {
if (defc.getClassLoader() != null) // detune due to 6939196
assertEquals(typeMaybeWithSelf.dropParameterTypes(0,1),
target.type().dropParameterTypes(0,1));
else // FIXME: use only this test when 6939196 is fixed
if (isSpecial) if (isSpecial)
assertEquals(specialCaller, target.type().parameterType(0)); assertEquals(specialCaller, target.type().parameterType(0));
else else
@ -1851,6 +1843,39 @@ public class MethodHandlesTest {
} }
} }
static Example userMethod(Object o, String s, int i) {
called("userMethod", o, s, i);
return null;
}
@Test
public void testUserClassInSignature() throws Throwable {
if (CAN_SKIP_WORKING) return;
startTest("testUserClassInSignature");
Lookup lookup = MethodHandles.lookup();
String name; MethodType mt; MethodHandle mh;
Object[] args;
// Try a static method.
name = "userMethod";
mt = MethodType.methodType(Example.class, Object.class, String.class, int.class);
mh = lookup.findStatic(lookup.lookupClass(), name, mt);
assertEquals(mt, mh.type());
assertEquals(Example.class, mh.type().returnType());
args = randomArgs(mh.type().parameterArray());
mh.invokeVarargs(args);
assertCalled(name, args);
// Try a virtual method.
name = "v2";
mt = MethodType.methodType(Object.class, Object.class, int.class);
mh = lookup.findVirtual(Example.class, name, mt);
assertEquals(mt, mh.type().dropParameterTypes(0,1));
assertTrue(mh.type().parameterList().contains(Example.class));
args = randomArgs(mh.type().parameterArray());
mh.invokeVarargs(args);
assertCalled(name, args);
}
} }
// Local abbreviated copy of sun.dyn.util.ValueConversions // Local abbreviated copy of sun.dyn.util.ValueConversions
class ValueConversions { class ValueConversions {