JDK-8136614 : Accessibility bridges are not created for default methods
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8,9
  • Priority: P4
  • Status: Open
  • Resolution: Unresolved
  • OS: generic
  • CPU: x86
  • Submitted: 2015-08-23
  • Updated: 2016-07-21
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbd_majorUnresolved
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java full version "1.8.0_60-b27"

ADDITIONAL OS VERSION INFORMATION :
Darwin x86_64

A DESCRIPTION OF THE PROBLEM :
To work around JDK-6342411, javac emits "accessibility" bridges when public methods are inherited from non-public superclasses into public derived classes.

Accessibility bridges are not emitted for defender methods, leading to spurious java.lang.IllegalAccessException when those methods are invoked reflectively on the derived class.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
javac Test.java pkg/A.java pkg/B.java
java Test

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I expected the program to print "hi".
ACTUAL -
The program failed with an IllegalAccessException.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.IllegalAccessException: Class Test can not access a member of class pkg.A with modifiers "public"
	at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
	at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
	at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
	at java.lang.reflect.Method.invoke(Method.java:490)
	at Test.main(Test.java:3)

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
=== pkg/A.java
package pkg;
interface A {
  default public void f() {
    System.err.println("hi");
  }
}
=== pkg/B.java
package pkg;
public class B implements A {}
=== Test.java
class Test {
  public static void main(String[] args) throws Exception {
    Class.forName("pkg.A").getMethod("f").invoke(new pkg.B(), new Object[]{});
  }
}
===
---------- END SOURCE ----------


Comments
Problem stems from com.sun.tools.javac.code.Symbol.MethodSymbol#binaryImplementation and com.sun.tools.javac.code.Symbol.MethodSymbol#implementation(com.sun.tools.javac.code.Symbol.TypeSymbol, com.sun.tools.javac.code.Types, boolean, com.sun.tools.javac.util.Filter<com.sun.tools.javac.code.Symbol>) not treating inherited default implementations as implementations.
05-10-2015

I don't think even if a bridge method is emitted, the problem would go away for the given code snippet as long as the Class object materialized with Class.forName happens to be private to another package. See that the following code also fails with java.lang.IllegalAccessException even though there are no default methods involved in the picture: // pkg/B.java package pkg; class C { public void c() { System.err.println("C"); } } public class B extends C {} // ---------------- X.java: public class X { public static void main(String[] args) throws Exception { Class.forName("pkg.C").getMethod("c").invoke(new pkg.B(), new Object[]{}); } } Running the program results in Exception in thread "main" java.lang.IllegalAccessException: Class X can not access a member of class pkg.C with modifiers "public" at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102) at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296) at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288) at java.lang.reflect.Method.invoke(Method.java:490) at X.main(X.java:3) On the other hand if the class.forName call were to be: Class.forName("pkg.B").getMethod("c").invoke(new pkg.B(), new Object[]{}); it runs fine. Yes, a bridge method is missing for the package private interface case.
05-10-2015

Attached Test case was executed on JDK 8 -Fail , 8u60 -Fail and 9EA.-fail The issue is specific to defender methods. Moving to dev-team for further action.
16-09-2015