2

Many books said that java final instance methods(not private) use static binding, and other instance methods(not private) use dynamic binding. However When compiled, both of them use "invokevirtual" JVM instruction. Do final methods and non final methods are distinguished When JVM executes "invokevirtual" instructions ? I originally think that final methods use "invokespecial" as private instance methods because they all use static binding.

yufengwang
  • 21
  • 1

2 Answers2

4

The compiled form is a direct consequence of JLS §13.4.17 in the chapter 13, “Binary Compatibility”:

13.4.17. final Methods

Changing a method that is declared final to no longer be declared final does not break compatibility with pre-existing binaries.

This implies that the form of the caller should not reflect whether the target method was final at compile time or not (or when there was a different representation, it was not allowed to make a practical difference at runtime).

To compare with other forms of invocations, it is not possible to remove a static modifier without breaking compatibility with callers, hence, it is consistent to encode the form of invocation with a dedicated invokestatic instruction.

For invocations of private methods, the caller has to be in the same class, hence, gets recompiled when adding or removing a private modifier (considering valid callers only), so there’s no problem using invokespecial when invoking a private method within the same class. Since JDK 11, private methods might get invoked by callers in other classes belonging to the same nest group; in that case, these callers in other classes do not use invokespecial.

So the distinction between final and non-final methods does indeed happen at runtime, when the JVM knows the actual target method, if such a distinction happens at all. A conforming JVM has to reject classes trying to override a final method, but they don’t need to perform optimizations regarding invocations. In practice, today’s JVMs are capable of optimizing invocations of all methods that have not been overridden, regardless of whether this properties has been enforced by a final modifier. The only difference is that loading a new class into the JVM that does override a non-final method may cause de-optimization of the callers.

Community
  • 1
  • 1
Holger
  • 285,553
  • 42
  • 434
  • 765
0

There is no other bytecode instruction to call an instance method declared by a class other than invokevirtual. Its name is confusing. It could also be named like invokeClassMethod or invokeclass. Actually compiler does not treat final methods specially. invokespecial is used to invoke constructors and static initializers.

glee8e
  • 6,180
  • 4
  • 31
  • 51
  • 2
    Not strictly true. You can `invokespecial` just fine on normal methods and this is done for super calls for example. – yawkat May 25 '18 at 10:21