Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

invokestatic on static method in interface

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.

like image 545
Radim Vansa Avatar asked Dec 18 '15 17:12

Radim Vansa


People also ask

Can we use static method in interface?

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.

Are static methods in interfaces inherited?

Static methods in interfaces are never inherited.

Why we Cannot override static method?

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.

Can we override static method in interface in Java 8?

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.


1 Answers

Well, before Java 8, static methods in interfaces 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:

  1. 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)

  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 interfaces, 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.

like image 191
Holger Avatar answered Nov 14 '22 21:11

Holger