From jvilk at cs.umass.edu Wed Dec 31 20:51:43 2014 From: jvilk at cs.umass.edu (John Vilk) Date: Wed, 31 Dec 2014 20:51:43 -0000 Subject: JLS and JVMS SE8 Disagreement: Method Resolution Behavior with Multiple Maximally-Specific Default Methods Message-ID: Hello, I recently noticed a disagreement between the JLS and the JVMS for SE8 concerning the scenario where multiple direct superinterfaces of a class provide a default method for a method reference with the same name and signature. I believe this is a bug in the JVM specification, which specifies behavior that is not present in the reference implementation of the specification, and which differs from the behavior specified in the JLS. The JVM specification states the following should occur in the section on method resolution, ?5.4.3.3 , should there be no single maximally-specific default method (meaning, there are multiple) (emphasis mine): Otherwise, if any superinterface of C declares a method with the name and descriptor specified by the method reference that has neither its ACC_PRIVATE flag nor its ACC_STATIC flag set, *one of these is arbitrarily chosen and method lookup succeeds.* However, the JLS specification states the following in the section on Interface Method Declarations in the binary compatibility chapter, ?13.5.6 : Adding a default method, or changing a method from abstract to default, does not break compatibility with pre-existing binaries, but may *cause an IncompatibleClassChangeError if a pre-existing binary attempts to invoke the method.* This section of the JLS contains a full example that exemplifies the specification bug I am describing in this email. In particular, the JLS states: If Cowboy is recompiled but not CowboyArtist, then running the new binary with the existing binary for CowboyArtist will link without error *but cause an IncompatibleClassChangeError when main attempts to invoke draw().* However, this behavior description is in contrast to the JVM specification, which claims that one of the draw methods should be arbitrarily chosen and invoked. Using separate compilation on the example, I verified that the JVM does, in fact, throw an IncompatibleClassChangeError, which disagrees with the behavior specified in the JVMS: $ java example/CowboyArtist Exception in thread "main" java.lang.IncompatibleClassChangeError: Conflicting default methods: example/Cowboy.draw example/Painter.draw at example.CowboyArtist.draw(CowboyArtist.java) at example.CowboyArtist.main(CowboyArtist.java:6) Since this behavior originates in the JVM, rather than in the bytecode produced from the Java Compiler, it should be included in the JVM specification. Thus, to fix this specification bug, I propose that the quoted section of the JVMS from the method resolution section be replaced with the following text: Otherwise, if there are multiple maximally-specific superinterface methods of C for the name and descriptor specified by the method reference, method resolution throws an IncompatibleClassChangeError. I believe the above text captures the behavior of the current reference implementation, and is in line with the JLS. Let me know if you have any questions, comments, or if you find a mistake in my reasoning above. It is very possible that I am missing a subtlety. Thanks for reading! John