Well, before Java 8, static
methods in interface
s were not allowed, so obviously, any attempt to use them in a previous version or within a class file having an older version is doomed to fail, regardless of how it is implemented in Java 8.
Before Java 8, we had the following two rules:
The class_index item of a CONSTANT_Methodref_info
structure must be a class type, not an interface type.
The class_index item of a CONSTANT_InterfaceMethodref_info
structure must be an interface type.
(See JVMSpec 7 §4.4.2)
The method descriptor of an invokestatic
must refer a CONSTANT_Methodref_info
entry
(See JVMSpec 7 §6.5)
The run-time constant pool item at that index must be a symbolic reference to a method (§5.1), which gives the name and descriptor (§4.3.3) of the method as well as a symbolic reference to the class in which the method is to be found.
It might not look that clear that “symbolic reference to a method” precludes interface methods, but without that assumption we had no difference to the behavior of Java 8 at all. It also will become clearer by comparing with the JVM specification for Java 8 or considering that interface methods were always implied to be non-static
.
It should be obvious that for adding support for static
methods in interface
s, to be invoked via invokestatic
, at least one rule has to change.
If we look at the rules and their wording, we see that the first one is quite clear whereas in the second one, it’s not entirely obvious that “symbolic reference to a method” is referring to CONSTANT_Methodref_info
entries and precluding a “symbolic reference to an interface method”. The decision was to change that rule and make the wording clearer at the same time:
(JVMSpec 8 §6.5):
The run-time constant pool item at that index must be a symbolic reference to a method or an interface method (§5.1), which gives the name and descriptor (§4.3.3) of the method as well as a symbolic reference to the class or interface in which the method is to be found.
Now it’s clear that invokestatic
may refer to interface methods and thus the first rule doesn’t need to be touched, and it hasn’t been touched. But note that the first rule never mandated the interface methods to be non-static
. It’s only about whether the declaring type is an interface
or not.
This obviously reduces the value of the distinction between CONSTANT_Methodref_info
and CONSTANT_InterfaceMethodref_info
but this was unavoidable. If the first rule was relaxed instead, it would also soften this distinction.
But there was a strong reason to change the invocation side instead: due to the introduction of default
methods, there is now the possibility to invoke an overridden default
method via invokespecial
just like other overridden non-abstract
methods before. Thus, invokespecial
may now refer to interface
methods as well.
Insisting on a match between the type of the invocation instruction and the constant pool entry type, like with the old rules, would imply that in the case of default
methods, we would sometimes need two pool entries to describe the same target method, one for invokeinterface
and a different one for invokespecial
.