JDK-8024647 : Default method resolution with private superclass method
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2013-09-11
  • Updated: 2014-06-26
  • Resolved: 2013-09-17
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.
JDK 8 Other
8Fixed hs25Fixed
Related Reports
Relates :  
Relates :  
Description
The currently-specified behavior of resolution is that a private class method takes priority over an interface method.  (This is a problem -- see JDK-8021581.)

When default methods are involved, this rule is not being followed, and there are some inconsistencies.

Example 1 is the expected behavior for all 3 cases.

There may be some similar inconsistencies when package-access methods are involved.

-----
Example 1 (no default):

public class A {
 private void m() { System.out.println("A.m"); }
 public static void main(String... args) { B b = new C(); b.m(); }
}

public interface I {
 public void m();
}

public abstract class B extends A implements I {
}

public class C extends B {
 public void m() { System.out.println("C.m"); }
}

public class Test {
 public static void main(String... args) { B b = new C(); b.m(); }
}

java Test
Exception in thread "main" java.lang.IllegalAccessError: tried to access method A.m()V from class Test

java A
A.m

-----
Example 2 (default, overridden):

public class A {
 private void m() { System.out.println("A.m"); }
 public static void main(String... args) { B b = new C(); b.m(); }
}

public interface I {
 public default void m() { System.out.println("I.m"); }
}

public abstract class B extends A implements I {
}

public class C extends B {
  public void m() { System.out.println("C.m"); }
}

public class Test {
 public static void main(String... args) { B b = new C(); b.m(); }
}

java Test
C.m

java A
C.m

-----
Example 3 (default, not overridden):

public class A {
 private void m() { System.out.println("A.m"); }
 public static void main(String... args) { B b = new C(); b.m(); }
}

public interface I {
 public default void m() { System.out.println("I.m"); }
}

public abstract class B extends A implements I {
}

public class C extends B {
}

public class Test {
 public static void main(String... args) { B b = new C(); b.m(); }
}

java Test
Exception in thread "main" java.lang.IllegalAccessError: tried to access method A.m()V from class B

java A
Exception in thread "main" java.lang.IllegalAccessError: tried to access method A.m()V from class B

Comments
Test cases should be added to vm sqe defmeth tests. See 8022576
16-09-2013

JDK8 fix to have all three examples match example 1 behavior.
14-09-2013

The spec bug (JDK-8021581) will not be addressed for 8. So the correct behavior is, definitively, to match Example 1 in all cases.
13-09-2013