invokespecial of default methods in unrelated interfaces
Brian Goetz
brian.goetz at oracle.com
Thu Jun 13 11:14:54 PDT 2013
Well, I wouldn't expect C code to be invoked in any case, but a crash is
probably not a good result.
I believe the intent was to have invokespecial reject an invocation if
the named class was not an immediate supertype of the invoker. There
may also be additional restrictions that the compiler imposes, designed
to prevent "level skipping" usages, that may or may not need to also be
enforced by the VM.
On 6/13/2013 1:31 PM, Daniel Heidinga wrote:
> We've put together a defender method test case using invokespecial and
> we'd like some confirmation of our spec interpretation. The testcase is:
>
> interface A {
> default void m(){ System.out.println("A"); };
> }
> interface B {
> default void m(){ System.out.println("B"); };
> interface C {
> default void m(){ System.out.println("C"); };
> }
> class D implements A, B {
> void m() {
> C.super.m(); // Note, D does not implement C
> }
> public static void main(String[] args) {
> new D().m();
> }
> }
>
> While javac won't compile this, it is legal bytecode (generated with ASM
> because class D is unrelated to interface C). Executing 'new D().m()'
> unfortunately crashes Hotspot b93.
>
> The lambda changes to the JVM spec for invokespecial indicate 'The named
> method is resolved (5.4.3.3)'. 5.4.3.3 states "Method resolution
> attempts to look up the referenced method in C and its superclasses".
> As C clearly has an implementation of m(), resolution should succeed
> and C.m() should be called. (As an aside, there is an issue with
> invokespecial referencing 5.4.3.3 for interface sends: "If C is an
> interface, method resolution throws an IncompatibleClassChangeError.")
>
> Does anyone disagree with this interpretation of the spec?
>
> --Dan
>
More information about the lambda-spec-observers
mailing list