ACC_SUPER 这个标志是为了纠正 invokespecial 在调用父类方法存在的版本问题。invokespecial是一个调用方法的字节码指令,用在调用构造方法、本类private方法、父类非虚方法3种场景(有一点要注意的是,JDK1.1之前,invokespecial 调用指定方法)它调用指定前两个调用没有问题,在调用父类方法时,存在版本的问题:
组建A,版本1:
public class GrandParent {
protected void myMethod() {
// ...
}
}
public class Parent extends GrandParent {
}
调用方B,版本1:
public class Child extends Parent {
protected void myMethod() {
// ...
super.myMethod();
}
}
版本1中的调用方调用super.myMethod()时,由于调用指定的方法,会调到GrandParent.myMethod(),这时没有问题
作者修改了组建A:
public class GrandParent {
protected void myMethod() {
// ...
}
}
public class Parent extends GrandParent {
protected void myMethod() {
// ...
super.myMethod();
}
}
这时调用方,在没有重新编译的情况下,仍然会调用到GrandParent.myMethod(),这显然不符合作者的预期。
JDK1.1之前,invokespecial 调用指定方法,1.1中变成了搜索父类的最近的方法,但前提是设置了 ACC_SUPER 标志位,如果设置了ACC_SUPER,这时调用方,在没有重新编译的情况下,会搜索到Parent.myMethod(),这个问题得到了解决。
详见:
http://weblog.ikvm.net/PermaLink.aspx?guid=99fcff6c-8ab7-4358-9467-ddf71dd20acd