Disassembling some Java 8 code I found out that some invokestatic
calls on static methods in interface (particularly this was java.util.function.Function.identity()
) uses InterfaceMethodRef in const pool; this is what javap -s -c -v p
show me:
15: invokestatic #66 // InterfaceMethod java/util/function/Function.identity:()Ljava/util/function/Function;
According to JVM 8 spec this is not possible, and when I've used this instruction in classfile with version Java 7 (major version=51
), it has thrown VerifyError on this instruction.
However, when I've changed the major version to 52
, it started working like a charm. Note that I am running on Oracle JDK 1.8.0_60. I wonder why this change was needed (the invoked method is linked statically, isn't it?) and whether this is documented anywhere.
Similar to Default Method in Interface, the static method in an interface can be defined in the interface, but cannot be overridden in Implementation Classes. To use a static method, Interface name should be instantiated with it, as it is a part of the Interface only.
Static methods in interfaces are never inherited.
No, we cannot override static methods because method overriding is based on dynamic binding at runtime and the static methods are bonded using static binding at compile time. So, we cannot override static methods. The calling of method depends upon the type of object that calls the static method.
You cannot override the static method of the interface; you can just access them using the name of the interface. If you try to override a static method of an interface by defining a similar method in the implementing interface, it will be considered as another (static) method of the class.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With