When an inherited non-static field or method is looked up in a class C using Lookup.findVirtual(C...), etc., the JSR 292 API, the first argument of the resulting method handle must be the receiver ('this'), and must be the requested class (or more specific, in the case of findSpecial or a lookup of a protected method).
But currently, if a supertype T defines the looked-up method or field and C inherits it, the returned method handle might have the more specific initial type T.
The relevant javadoc (and 292 spec.) is as follows:
* The formal parameter {@code this} stands for the self-reference of type {@code C};
* if it is present, it is always the leading argument to the method handle invocation.
* (In the case of some {@code protected} members, {@code this} may be
* restricted in type to the lookup class; see below.)
Because of this bug, all of the assertions fail in the following example:
import java.lang.invoke.*;
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
class Test_0000000 {
interface Intf { void m1(); }
abstract class Super implements Intf { abstract void m2(); public int f2; }
abstract class Sub extends Super { }
public static void main(String... av) throws Throwable {
MethodHandle m1 = lookup().findVirtual(Sub.class, "m1", methodType(void.class));
System.out.println(m1);
MethodHandle m2 = lookup().findVirtual(Sub.class, "m2", methodType(void.class));
System.out.println(m2);
MethodHandle f2 = lookup().findGetter(Sub.class, "f2", int.class);
System.out.println(f2);
MethodHandle f2s = lookup().findSetter(Sub.class, "f2", int.class);
System.out.println(f2s);
assertEquals(Sub.class, m1.type().parameterType(0));
assertEquals(Sub.class, m2.type().parameterType(0));
assertEquals(Sub.class, f2.type().parameterType(0));
assertEquals(Sub.class, f2s.type().parameterType(0));
}
private static void assertEquals(Object expect, Object observe) {
if (java.util.Objects.equals(expect, observe)) return;
String msg = ("expected "+expect+" but observed "+observe);
System.out.println("FAILED: "+msg);
throw new AssertionError(msg);
}
}
Test: java/lang/invoke/7157574/Test7157574.java