码迷,mamicode.com
首页 > 编程语言 > 详细

【爱上Java8】ACC_SUPER和早期的invokespecial

时间:2014-08-27 18:53:28      阅读:326      评论:0      收藏:0      [点我收藏+]

标签:java8   java性能   优化   jvm   

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以支持一个正确的父类调用。

【爱上Java8】ACC_SUPER和早期的invokespecial

标签:java8   java性能   优化   jvm   

原文地址:http://blog.csdn.net/xinaij/article/details/38872851

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!