Is it possible to define method binding type by bytecode?

时间:2017-07-12 08:12:17

标签: java binding bytecode

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?

1 个答案:

答案 0 :(得分:2)

短语“来自Java规范”具有误导性,因为没有多个规范,因此只有the Java specification不包含引用的语句。

术语“早期绑定”和“后期绑定”不足以描述Java方法调用的可能性。

  1. 唯一在编译时解析其最终目标的方法调用是private方法和构造函数调用,以及自{8}以来staticinterface方法调用。

  2. 对于非static类型和interface方法调用的super方法调用,将在编译时设置目标类型,但JVM可以解析运行时指定类型的超类型的方法。尽管如此,解析后的目标方法在特定运行时永远不会改变,并且不需要为每个方法调用进行解析,因此一旦方法得到解决,它就是某种早期绑定。但是JVM通常会将解析推迟到调用指令的第一次实际执行。

  3. 对于剩余的实例方法调用类型,目标方法是否在编译时声明为final并不重要。这些调用总是以与invokevirtual指令相同的方式编码,这意味着根据接收器对象类型查找实际的目标方法。在编译调用者之后,您可以将方法更改为final或非final,而不会破坏兼容性(除非您覆盖之后转为final的方法)。

    当接收器类型为interface时,在编译时永远不会将其视为final,但仍会在运行时以final方式结束。

    当然,在解析之后,JVM可能会注意到目标方法已被声明为final并转向与上述第二种类型的“早期绑定”匹配的优化调用,另一方面,大多数JVM都是足够聪明,可以使用尚未声明final但仍未实际覆盖的方法(可能适用于大多数方法)。因此,如果唯一的结果是应用于其他方法的优化,则调用final方法“早期绑定”的调用是毫无意义的。