-
Bug
-
Resolution: Not an Issue
-
P5
-
9
-
None
MethodHandle::Lookup factories restrict receiver type to the lookup class when a protected instance member is accessed.
That's discussed in the class-level Javadoc of Lookup (paragraph "If the desired member is protected, the usual JVM rules apply..."),
and, more formally, in the findVirtual's Javadoc: "The first argument will be of type refc if the lookup class has full privileges to access the member. Otherwise the member must be protected and the first argument will be restricted in type to the lookup class."
However, Javadocs of other factory methods don't specify that.
The affected methods are:
unreflect
findGetter
findSetter
unreflectGetter
unreflectSetter
findVarHandle
unreflectVarHandle
Example:
====================================
public class B extends A {
public static void main(String[] args) throws Throwable {
MethodHandle mh = lookup().findGetter(A.class, "f", int.class);
System.out.println(mh.type());
MethodHandle mh2 = lookup().findSetter(A.class, "f", int.class);
System.out.println(mh2.type());
VarHandle vh = lookup().findVarHandle(A.class, "f", int.class);
System.out.println(vh.coordinateTypes());
Field f = A.class.getDeclaredField("f");
MethodHandle mh3 = lookup().unreflectGetter(f);
System.out.println(mh3.type());
MethodHandle mh4 = lookup().unreflectSetter(f);
System.out.println(mh4.type());
VarHandle vh2 = lookup().unreflectVarHandle(f);
System.out.println(vh2.coordinateTypes());
Method m = A.class.getDeclaredMethod("m");
MethodHandle mh5 = lookup().unreflect(m);
System.out.println(mh5);
}
}
package pkg;
public class A {
protected int f;
protected void m() { }
}
====================================
Output (note that all recevier types are B, not A):
(B)int
(B,int)void
[class B]
(B)int
(B,int)void
[class B]
MethodHandle(B)void
That's discussed in the class-level Javadoc of Lookup (paragraph "If the desired member is protected, the usual JVM rules apply..."),
and, more formally, in the findVirtual's Javadoc: "The first argument will be of type refc if the lookup class has full privileges to access the member. Otherwise the member must be protected and the first argument will be restricted in type to the lookup class."
However, Javadocs of other factory methods don't specify that.
The affected methods are:
unreflect
findGetter
findSetter
unreflectGetter
unreflectSetter
findVarHandle
unreflectVarHandle
Example:
====================================
public class B extends A {
public static void main(String[] args) throws Throwable {
MethodHandle mh = lookup().findGetter(A.class, "f", int.class);
System.out.println(mh.type());
MethodHandle mh2 = lookup().findSetter(A.class, "f", int.class);
System.out.println(mh2.type());
VarHandle vh = lookup().findVarHandle(A.class, "f", int.class);
System.out.println(vh.coordinateTypes());
Field f = A.class.getDeclaredField("f");
MethodHandle mh3 = lookup().unreflectGetter(f);
System.out.println(mh3.type());
MethodHandle mh4 = lookup().unreflectSetter(f);
System.out.println(mh4.type());
VarHandle vh2 = lookup().unreflectVarHandle(f);
System.out.println(vh2.coordinateTypes());
Method m = A.class.getDeclaredMethod("m");
MethodHandle mh5 = lookup().unreflect(m);
System.out.println(mh5);
}
}
package pkg;
public class A {
protected int f;
protected void m() { }
}
====================================
Output (note that all recevier types are B, not A):
(B)int
(B,int)void
[class B]
(B)int
(B,int)void
[class B]
MethodHandle(B)void