JDK-8028438 : Lambda: default methods static superclass method masking default
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: hs25
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2013-11-15
  • Updated: 2020-08-18
  • Resolved: 2013-12-03
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
Static method in a superclass is interfering with the default method list creation.

interface I {
  default String foo() {
      return "default";
  }
}

public class A {
  public static String foo() { return "static"; }
}

public class B extends A implements I {
  public static void main(String[] args) {
      try {
          System.out.println(new B().foo());
      } catch (Throwable t) {
          System.out.println("invokevirtual: new B().foo() -> " + t);
      }

      try {
          System.out.println(((I)(new B())).foo());
      } catch (Throwable t) {
          System.out.println("invokeinterface: ((I)(new B()).foo() -> " + t);
      }
  }
}

See attached.

When i compile (separately) and run using tl or hotspot-rt the output is:

invokevirtual: new B().foo() -> java.lang.IncompatibleClassChangeError: Expecting non-static method B.foo()Ljava/lang/String;
invokeinterface: ((I)(new B()).foo() -> java.lang.AbstractMethodError: B.foo()Ljava/lang/String;

My initial translation of this is that the first example is behaving correctly.
The second example looks like a bug to me - I believe invokeinterface ((new B()).foo() should print "default")

Note: inside the code, the default method processing is not finding any slots to fill, so
the initial miranda list appears to not contain foo().
Comments
Release team: Approved for fixing
03-12-2013

SQE is OK with fixing this in JDK8
02-12-2013

Justification: This fix is needed for default methods to work properly, otherwise the correct default method may not be found. This is part of ensuring the correct behavior of default methods relative to static methods. Risk: low, any bugs should be very corner cases. Tested with: defmeth tests - two new ones added, jck.vm, jck.lang, jtreg java.util, java.lang, lambda, langtools lambda, nsk invoke* tests, jtreg hotspot runtime, compiler, nsk vm.quick, vm.mlvm
02-12-2013

Thanks to Harold for the fix in LinkResolver.cpp for lookup_instance_method_in_klasses.
01-12-2013

My initial analysis is that during the default method logic (defaultMethods.cpp) we need to skip static methods in superclasses, which should not hide methods in superinterface instance methods, to match the current spec. I do not know whether a local static method should be considered as hiding superinterface instance methods - worth writing a test so we can check with each other and then with Dan what the expected behavior should be. The local static method should not hide the superinterface instance method for the selection process which ignores statics. See next comment, test case added for that as well.
01-12-2013

Test cases added to defmeth StaticMethodsTest in review in parallel. New test cases testStaticSuperClassVsDefaultSuperInterface and testStaticLocalVsDefaultSuperInterface - in both examples, this fix is required for Test2_xxx to pass.
01-12-2013

Thank you to Paul Sandoz for identifying this issue.
15-11-2013