ACC_SUPER簡介

class文件中的access flag記錄了一個類的相關信息,比如public abstract final等等。其中有一個值ACC_SUPER。現理解如下:
ACC_SUPER是用來表示如何調用父類的方法。在jdk1.1之前,jvm使用一種invokenonvirtual的指令,調用父類方法。這個方法就是現在的invokespecial 前身。既然連名字都改過了,他們的實現差距可以認爲已經比較大了。invokenonvirtual是不會進行虛函數查找的,也就是總是靜態綁定。
我們知道,在class文件中使用CONSTANT_Methodref_info來表示一個方法。CONSTANT_Methodref_info中有一個指向類的成員,invokenonvirtual會直接使用CONSTANT_Methodref_info中的類進行方法調用,而不去進行虛函數查找。因此,需要由編譯器在編譯時就綁定到最近的父類。jdk1.1以後,jvm會忽略CONSTANT_Methodref_info 中的class,轉而去查找最近的超類方法。
這個改動是非常有意義的,我們來一下下面的代碼:
有一個組件A

public class GrandParent {
  protected void myMethod() {
    // ...
  }
}
public class Parent extends GrandParent {
}


組件B使用了組件A

public class Child extends Parent {
  protected void myMethod() {
    // ...
    super.myMethod();
  }
}


很明顯,組件B肯定是用了GrandParent.myMethod()。因爲Parent裏沒有myMethod方法。但是,如果你更新了組件A

public class GrandParent {
  protected void myMethod() {
    // ...
  }
}
public class Parent extends GrandParent {
  protected void myMethod() {
    // ...
    super.myMethod();
  }
}


這個時候,如果使用invokenonvirtual調用方式,你依然會運行GrandParent.myMethod()(在不重新編譯Child的情況下)。因爲這是在編譯時綁定的。使用了CONSTANT_Methodref_info裏的class作爲調用基準。這個結果顯然不是你想看到的。
但如果使用了新的invokespecial ,他就會搜索類層次,找到最近的一個父類進行方法調用,得到正確的結果。第2中方法就是設置了ACC_SUPER時的情況。
現在編譯器都會生成ACC_SUPER以支持一個正確的父類調用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章