From alex.buckley at oracle.com Thu Feb 12 00:24:23 2015 From: alex.buckley at oracle.com (Alex Buckley) Date: Wed, 11 Feb 2015 16:24:23 -0800 Subject: JLS and JVMS SE8 Disagreement: Method Resolution Behavior with Multiple Maximally-Specific Default Methods In-Reply-To: References: Message-ID: <54DBF2B7.4080804@oracle.com> Hi John, The ICCE is specified in JVMS 6.5, in the "Run-time Exceptions" section of invoke{interface,special,virtual}. It is this ICCE that JLS 13.5.6 relies on when describing whether adding a default method is binary compatible. The thing to remember is that resolution (JVMS 5.4.3.3) is just a preliminary step in the execution of invoke* bytecodes. It "starts" from the static type named in a symbolic reference. Selection (JVMS 6.5) is a distinct and fussier step. It "starts" from the dynamic type of the receiver object. Alex On 12/31/2014 12:51 PM, John Vilk wrote: > 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 > From jvilk at cs.umass.edu Thu Feb 12 04:04:08 2015 From: jvilk at cs.umass.edu (John Vilk) Date: Wed, 11 Feb 2015 23:04:08 -0500 Subject: JLS and JVMS SE8 Disagreement: Method Resolution Behavior with Multiple Maximally-Specific Default Methods In-Reply-To: <54DBF2B7.4080804@oracle.com> References: <54DBF2B7.4080804@oracle.com> Message-ID: Ah, I see! Thank you for the clarification. John On Wed, Feb 11, 2015 at 7:24 PM, Alex Buckley wrote: > Hi John, > > The ICCE is specified in JVMS 6.5, in the "Run-time Exceptions" section of > invoke{interface,special,virtual}. It is this ICCE that JLS 13.5.6 relies > on when describing whether adding a default method is binary compatible. > > The thing to remember is that resolution (JVMS 5.4.3.3) is just a > preliminary step in the execution of invoke* bytecodes. It "starts" from > the static type named in a symbolic reference. Selection (JVMS 6.5) is a > distinct and fussier step. It "starts" from the dynamic type of the > receiver object. > > Alex > > On 12/31/2014 12:51 PM, John Vilk wrote: > >> 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 >> > jvms-5.html#jvms-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 >> >>