【爱上Java8】ACC_SUPER和早期的invokespecial

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

1
2
3
4
5
6
7
public  class GrandParent  {
   protected  void myMethod ( )  {
     // ...
   }
}
public  class Parent  extends GrandParent  {
}

组件B使用了组件A

1
2
3
4
5
6
public  class Child  extends Parent  {
   protected  void myMethod ( )  {
     // ...
     super. myMethod ( ) ;
   }
}

很明显,组件B肯定是用了GrandParent.myMethod()。因为Parent里没有myMethod方法。但是,如果你更新了组件A

1
2
3
4
5
6
7
8
9
10
11
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以支持一个正确的父类调用。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值