Issue with hypothetical bridge methods and JDK-6342411
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Wed Aug 5 20:58:31 UTC 2015
This is related to the discussion we had; a long tail of the current
approach for bridge calculation is that sometimes we need hypothetical
stuff which is there just to make Symbol.binaryOverrides work correctly.
I'm not completely surprised this sometimes lead to unexpected behavior...
Maurizio
On 03/08/15 22:26, Liam Miller-Cushon wrote:
> I think I found a bug in the interaction between 'hypothetical' bridge
> methods and the workaround for JDK-6342411.
>
> A hypothetical bridge method "is not strictly necessary in the binary,
> but is represented in the symbol table to detect erasure clashes." [1]
>
> Bridges are required to work around JDK-6342411 when a non-public
> super class declares a public method that's inherited into a public
> derived class. Without the bridge, reflectively invoking the method on
> the derived class fails with `IllegalAccessException: can not access a
> member with modifiers "public"`. [2][3]
>
> The issue I found occurs when a bridge method candidate qualifies as a
> hypothetical bridge *and* is necessary to work around JDK-6342411. The
> path for hypothetical bridges wins, so the bridge is entered in the
> symbol table but not generated in the binary, and attempts to invoke
> it reflectively fail.
>
> I've attached a patch with a regression test and a possible fix.
>
> Here's the repro:
>
> === ./p/I.java ===
> package p;
>
> public interface I<T> {
> void f(T t);
> }
> === ./p/B.java ===
> package p;
>
> public class B extends A<String> {}
> === ./p/A.java ===
> package p;
>
> class A<T> implements I<T> {
> public void f(T t) {}
> }
> === ./Test.java ===
> import java.lang.reflect.Method;
>
> public class Test {
> public static void main(String[] args) throws Exception {
> Method m = Class.forName("p.B").getMethod("f", Object.class);
> m.invoke(new p.B(), new Object[]{null});
> }
> }
> ===
>
> $ javac p/I.java p/A.java p/B.java Test.java
> $ java Test
> Exception in thread "main" java.lang.IllegalAccessException: Class
> Test can not access a member of class p.A with modifiers "public"
> at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:101)
> at
> java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:295)
> at
> java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:287)
> at java.lang.reflect.Method.invoke(Method.java:476)
> at Test.main(Test.java:6)
>
> [1]
> http://hg.openjdk.java.net/jdk9/dev/langtools/file/7eef740c1482/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java#l238
> [2]
> http://hg.openjdk.java.net/jdk9/dev/langtools/file/7eef740c1482/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java#l364
> [3] https://bugs.openjdk.java.net/browse/JDK-6342411
More information about the compiler-dev
mailing list