4

From following sources:

https://www.amazon.com/Java-Complete-Reference-Herbert-Schildt/dp/0071808558

Chapter 8 : Using final with Inheritance

http://javarevisited.blogspot.com.by/2012/03/what-is-static-and-dynamic-binding-in.html

Static Vs. Dynamic Binding in Java

for private,static,final methods early(static) method binding should be used

. So I've created a little test

class MethodRefDemo2
{
  public static void main( String args[] )
  {
    BindingTest bindingTest = new BindingTest();
    bindingTest.printEarly();
    bindingTest.printLate();
  }
}

class BindingTest
{
  private String early = "static";
  private String late = "dynamic";

  final String printEarly()
  {
    return early;
  }

  String printLate()
  {
    return late;
  }
}

So as I think, these two methods should have different binding types. Checking byte code:

 public static main([Ljava/lang/String;)V
   L0
    LINENUMBER 8 L0
    NEW spring/BindingTest
    DUP
    INVOKESPECIAL spring/BindingTest.<init> ()V
    ASTORE 1
   L1
    LINENUMBER 9 L1
    ALOAD 1
    INVOKEVIRTUAL spring/BindingTest.printEarly ()Ljava/lang/String;
    POP
   L2
    LINENUMBER 10 L2
    ALOAD 1
    INVOKEVIRTUAL spring/BindingTest.printLate ()Ljava/lang/String;
    POP
   L3
    LINENUMBER 11 L3
    RETURN
   L4
    LOCALVARIABLE args [Ljava/lang/String; L0 L4 0
    LOCALVARIABLE bindingTest Lspring/BindingTest; L1 L4 1
    MAXSTACK = 2
    MAXLOCALS = 2

Here i see two INVOKEVIRTUAL instructions. So is there any way to determine what kind of binding was used by the class byte code? And if no, how can i determine binding type?

Ivan Lymar
  • 2,180
  • 11
  • 26

1 Answers1

3

The phrase “From a java specification” is misleading, as there are not multiple specifications, so there is only the Java specification which doesn’t contain the cited statement.

The terms “early binding” and “late binding” are not sufficient to describe the possibilities of Java method invocations.

  1. The only method invocations whose final target is resolved at compile time, are private methods and constructor invocations and, since Java 8, static method invocations on interface types.

  2. For static method invocations on non-interface types and for super method invocations, there will be a target type set at compile time, but the JVM may resolve the method in a super type of the specified type at runtime. Still, that resolved target method will never change in a particular runtime and doesn’t need to be resolved for every method invocation, so it’s some kind of early binding, once the method has been resolved. But JVMs typically defer the resolving to the first actual execution of the invocation instruction.

  3. For the remaining invocation type of instance methods, it doesn’t matter whether the target method has been declared final at compile-time or not. These invocations are always encoded the same way, as invokevirtual instruction, which implies looking up the actual target method based on the receiver object type. You can change the method to final or non-final after compiling the caller without breaking the compatibility (unless you override a method that is turned to final afterwards).

    When the receiver type is an interface, it can never be considered final at compile time, but still end up at a final method at runtime.

    Of course, after resolving, a JVM may notice that the target method has been declared final and turn to an optimized invocation matching “early binding” of the second kind above, on the other hand, most JVMs are smart enough to do the same with methods which have not been declared final but still not actually overridden (which might apply to the majority of all methods). So it would be pointless to call the invocation of a final method “early binding”, if the only consequence is an optimization that is applied to other methods as well.

Holger
  • 285,553
  • 42
  • 434
  • 765
  • Changed the information source. I thought that these guys used specification, that is why i made my question easier and referenced java spec, sorry for that.Checked doc by myself, there is no such statement, you are right. Does it mean that the book and the blog article are incorrect? – Ivan Lymar Jul 12 '17 at 18:03
  • 1
    @Ivan Lymar: let’s say imprecise or sloppy. They ignore the fact that classes may change after compilation (and practically do when a library evolves). So their examples work fine as they assume an environment that is the same for compilation and execution, but aren’t sufficient to show whether a decision was made at compile-time or runtime, as the result of that decision would be the same in either case. In the end, that doesn’t matter. “Late binding” means, the invocation might end up in different implementation methods depending on the actual receiver type, in contrast to “early binding”… – Holger Jul 12 '17 at 18:23