Duplicate :
|
|
Duplicate :
|
|
Relates :
|
|
Relates :
|
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. Attached is 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)
|