zoukankan      html  css  js  c++  java
  • java方法的虚分派和方法表

    java:方法的虚分派(virtual dispatch)和方法表(method table)

    Java方法调用的虚分派

    虚分配(Virtual Dispatch)

    首先从字节码中对方法的调用说起。Java的bytecode中方法的调用实现分为四种指令:

    invokevirtual为最常见的情况,包含virtual dispatch机制;

    invokerspecial是作为对private和构造方法的调用,绕过了virtual dispatch;

    invokeinterface的实现跟invokevirtual类似;

    invokestatic是对静态方法的调用;

    其中最复杂的要属invokevirtual指令,它涉及到了多态的特性,使用virtual dispatch做方法调用。

    virtual dispatch机制会首先从receiver(被调用方法的对象)的类的实现中查找对应的方法,如果没找到,则去父类查找,直找到函数并实现调用,而不是依赖于引用的类型。

    下面是一段有趣的代码。反映了virtual dispatch机制和一般的field访问的不同。

    运行结果:

    前两行输出中,对于Intro这个属性的访问,直接指向了父类中的变量,因为引用类型为父类。

    第二行对于target()的方法调用,则是指向了子类中的方法,虽然引用类型也为父类,但这是虚分配的结果,虚分配不管引用类型的,只查被调用对象的类型·。

    既然需分派机制是从被调用对象本身的类开始查找,那么对于一个覆盖了父类中某方法的子类的对象,是无法调用父类中那个被覆盖的方法的吗?

    在虚分派机制中这确实是不可以的。但却可以通过invokespecial实现。如下代码:

    func()就成功地调用了父类的方法target(),虽然target()已经被子类重写了。具体的调用细节,从字节码中可以看到:

    其中使用了invokespecial指令,而不是施行需分派策略的invokevirtual指令。

    方法表(Method Table)

    介绍了虚分派,接下来介绍是它的一种实现方法—方法表。类似于C++虚函数表vtbl。

    在有的JVM实现中,使用了方法表机制实现虚分派,而有时候,为了节省内存可能不采用方法表的实现。

    不要被方法表这个名字迷惑,它并不是记录所有方法的表。它是为虚分派服务,不会记录用invokestatic调用的静态方法和用invokespecial调用的够着函数和私有方法。

    JVM会在链接类的过程中,给类分配相应的方法表内存空间。每个类对应一个方法表。这些都是存在于method area区中的。这里与C++略有不同,C++中每个对象的第一个指针就是指向了相应的虚函数表。而Java中每个对象索引到对应的类,在对应的类数据中对应一个方法表。

    一种方法表的实现如下:

    父类的方法比子类的方法先得到解析,即父类的方法相对于子类的方法位于表的前列。

    表中每项对应于一个方法,索引到实际方法的实际代码上。如果子类重写了父类中某个方法的代码,则该方法第一次出现的位置的索引更换到子类的实现代码上,而不会在方法表中出现新的项。

    JVM运行时,当代码索引到一个方法时,是根据它在方法表中的偏移量来实现访问。(第一次执行到调用指令时,会执行解释,将符号索引替换为对应的直接索引)。

    invokeinterface与invokevirtual的比较

    当使用invokeinterface来调用方法时,由于不同的类可以实现同一interface,我们无法确定在某个类中的interface中的方法处在哪个位置。于是,也就无法解释CONSTANT_interfaceMethodref-info为直接索引,而必须每次都执行一次在methodtable中的搜索了。所以,在这种实现中,通过invokeinterface访问方法比通过invokevirtual访问明显慢很多。

  • 相关阅读:
    poj 1789 每个字符串不同的字母数代表两个结点间的权值 (MST)
    poj 1251 poj 1258 hdu 1863 poj 1287 poj 2421 hdu 1233 最小生成树模板题
    poj 1631 最多能有多少条不交叉的线 最大非降子序列 (LIS)
    hdu 5256 最少修改多少个数 能使原数列严格递增 (LIS)
    hdu 1025 上面n个点与下面n个点对应连线 求最多能连有多少条不相交的线 (LIS)
    Gym 100512F Funny Game (博弈+数论)
    UVa 12714 Two Points Revisited (水题,计算几何)
    UVa 12717 Fiasco (BFS模拟)
    UVa 12718 Dromicpalin Substrings (暴力)
    UVa 12716 && UVaLive 6657 GCD XOR (数论)
  • 原文地址:https://www.cnblogs.com/kexinxin/p/10147209.html
Copyright © 2011-2022 走看看