博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java方法的虚分派和方法表
阅读量:5023 次
发布时间:2019-06-12

本文共 1671 字,大约阅读时间需要 5 分钟。

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访问明显慢很多。

转载于:https://www.cnblogs.com/kexinxin/p/10147209.html

你可能感兴趣的文章
BirdNet: a 3D Object Detection Framework from LiDAR information
查看>>
icon fonts入门
查看>>
【Django】如何按天 小时等查询统计?
查看>>
HDU2191(多重背包)
查看>>
测试用例(一)
查看>>
【转】 mysql反引号的使用(防冲突)
查看>>
邮件中的样式问题
查看>>
AJAX 状态值与状态码详解
查看>>
php面向对象编程(oop)基础知识示例解释
查看>>
1.在数组中找到与给定总和的配对
查看>>
树的子结构
查看>>
关于根据Build Platform或者OS 加载x86或者x64 dll的问题
查看>>
程序员高效开发的几个技巧
查看>>
js-权威指南学习笔记19.2
查看>>
hexo 搭建博客
查看>>
关于 UIWebView 几个高级用法
查看>>
maven创建的项目中无法创建src/main/java 解决方案
查看>>
华为软件开发云测评报告二:代码检查
查看>>
集合1
查看>>
js 原生 ajax
查看>>