亚游,  战后,奥克恩曾接受美国总统亲自颁发的一枚国会勋章,但是人们始终还是无法理解为何发射出的鱼雷会飞向自己。有人认为这是鱼雷的方向系统出现错乱,就像人迷失方向一样。可是我们知道,这其实就是一个糟糕的巧合。(本文摘自《世界5000年可怕巧合》,作者:李杰卿 出版社:武汉出版社)

  新浪科技讯 北京时间7月22日消息,据悉Google已经提交诉状,反诉微软之前对于原全球副总裁李开复Google违反竞业禁止协议的指控,Google的反诉进一步加剧了Google微软之间剑拔弩张的气氛。白手起家什么意思  据悉,组委会提供的惊喜大奖包括:一等奖1名,奖品为价值10万元的小轿车一辆;二等奖3名,奖品为价值2万元的欧洲双人游;三等奖15名,奖品为价值4500元的新马泰双人游,惊喜大奖将在5月2日下午,在公证人员的监督下现场抽取。

发布于 2018-03-24 12:28:47 | 125 次阅读 | 评论: 0 | 来源: 网友投递

这里有新鲜出炉的精品教程,程序狗速度看过来!


下面小编就为大家带来一篇JVM 方法调用之动态分派(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

1. 动态分派

一个体现是重写(override)。下面的代码,运行结果很明显。


public class App {
 
 public static void main(String[] args) {
  Super object = new Sub();
  object.f();
 }
}

 class Super {
 public void f() {
  System.out.println("super : f()");
 }
 
 public void f(int i) {
  System.out.println("super : f(int)");
 }
}

class Sub extends Super{
 
 @Override
 public void f() {
  System.out.println("sub : f()");
 }
 
 @Override
 public void f(int i) {
  System.out.println("sub : f(int)");
 }
 
 public void f(char c) {
  System.out.println("sub : f(char)");
 }
}

最终输出sub : f();

那么虚拟机是怎么做到动态分派的呢?

不同的虚拟机有不同的实现,最常用的是使用虚方法表(Virtual Method Table)

2. 虚方法表

对于Super和Sub类,虚方法表大致如下:(灵魂画师)

上面的灵魂画作是什么意思呢?

虚方法表中存放着各个方法的实际入口地址。如果某个方法在子类中没有被重写,那子类的虚方法表里面的地址入口和父类相同签名的方法的地址入口是一致的,都指向父类的实现入口。如果子类中重写了这个方法,子类方法表中的地址将会替换为向子类实现版本的入口地址。

从上图主要得出几个信息:

a. 上图的大部分方法,子类Super和Sub均没有重写,那么都指向父类Object的类型数据。f()和f(int)方法,父类子类都实现了,那么两者就指向不同的实现地址。f(char)只在子类定义实现,自然指向子类的类型数据。

b. 为了程序实现上的方便,具有相同签名的方法,在父类,子类的虚方法表中都应当具有一样的索引序号,这样当类型变换时,仅需要变更查找的方法表,就可以从不同的虚方法表中按索引转换出所需要的入口地址。

3. 实例分析

以本文开头的代码进行分析。通过javap命令查看main方法的指令。

其中的invokevirtual指令详细调用过程是这样的:

1)指令中的#19指的是App类的常量池中第19个常量表的索引项。这个常量表(CONSTATN_Methodref_info)记录的是方法f()信息的符号引用,JVM首先根据这个符号引用找到调用方法f()的类的全限定名com.khlin.Super,这是因为变量object被声明为Super类型。

2) 在Super类型的方法表中查找方法f(),如果找到,则将方法f()在方法表中的索引项(具体值我不了解,这里将其记为index) 记录到App类的常量池中第19个常量表中(常量池解析)。因此,如果Super类型方法表中没有f(),那么即使Sub类型的方法表有该方法,也会报编译失败。

3)在调用invokevirtual指令前有一个aload_1指令,它会将开始创建中堆中的Sub对象的引用压入操作数栈。然后invokevirtual指令会根据这个Sub对象的引用首先找到堆中的Sub对象,然后进一步找到Sub对象所属类型的方法表。

4)这时,通过2)查找的index,可以定位到Sub类型方法表中的f()方法,然后通过直接地址找到该方法字节码所在的内存空间。这就是父类和子类相同签名的方法索引序号一致的用处。

4. 综合考虑:一个可能想错的例子

将本文开头的代码里的main方法稍作修改,调用其他的方法。


public static void main(String[] args) {
   Super object = new Sub();
   char c = 'a';
   object.f(c);
  }

结果将输出sub : f(int)

明明Sub方法里有完全一样类型的f(char)方法,却调用的是f(int).

相信通过前面的学习,已经可以明白原因了。

在object.f(c)调用时,虚拟机先到Super类的方法表里,查找最为合适的方法。

Super类里没有刚好参数为char的f(char)方法,按照前面静态分派和参数类型自动转换的学习,可以知道,编译器使用了除了f(char)之外最为合适的方法f(int)。获取到索引后,通过索引到实际对象的Sub方法表里找到f(int)方法,最终执行的就是Sub类的f(int)方法。

该方法的字节码指令证明了上述的论证。

以上这篇JVM 方法调用之动态分派(详解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持PHPERZ。



相关阅读 :
亚游JVM 方法调用之动态分派(详解)
JVM 方法调用之静态分派(详解)
基于JavaScript实现继承机制之构造函数方法对象冒充的使用详解
Java 虚拟机(JVM)之基本概念详解
redis内部数据结构之SDS简单动态字符串详解
ThinkPHP之getField使用详解
探讨php中方法的重写(覆载)详解
PHP中CURL方法curl_setopt()函数的参数详解
新手学PHP之数据库操作详解及乱码解决!
python之import机制详解
PHP启动windows应用程序、执行bat批处理、执行cmd命令的方法(exec、system函数详解)
swift之mutating关键字详解
最新网友评论  共有(0)条评论 发布评论 返回顶部
亚游

Copyright © 2007-2017 亚游 All Rights Reserved   冀ICP备14009818号  亚游  广告服务
跟踪偷拍举报官员违纪算侵犯隐私吗?专家这样说 美国新奥尔良市发生枪击事件 致3死7伤 库克暗示苹果将推出娱乐服务 明年有望推新闻订阅 5人讨薪归途车祸身亡:肇事货车超载司机负全责 中国冰球或直通北京冬奥 冰联:他们面临一大挑战 人大代表建议:推进儿童“反拐” 实行买卖同罪 Facebook事件不应成为开放平台业态“滑铁卢” 1岁男童误喝“蚊香液”中毒 洗胃用掉24瓶小苏打 山东省疾控中心官员自杀 曾是百白破疫苗评标委员 外媒:美国航企将于最后一刻 改用城市名标注台湾 上海女篮遗憾错止步半决赛 未来前途依旧光明 王小川:如果政策允许会优先考虑回A上市
曼联切尔西别惦记了!皇马金童:我只想留在皇马 大陆台海军演传递这些强烈信号 有能力解决台湾问题 多名80后官员落马 有人错误认为“政治虚票子实” 央视调查保健品市场乱象:办讲座送礼物假体检 印尼龙目岛地震已造成至少14人死亡162人受伤 布雷斯特冷负 18029期足彩任九开296注39665… 沈春耀谈宪法修正案:严格按照法定程序进行 扫黄打非办:取缔地下直播平台 下架未经审批网游 这件中国家务事 美国你到底要管到啥时候? 辽篮将与塞国劲旅热身 李晓旭贺天举月底归队 美团外卖回应合作海澜之家:将配送更多品类 新一轮机构改革箭已上弦 1998年改革亲历者忆旧事
北京新政:规范网络销售医疗器械 降低准入门槛 5G等技术突破带动VR回暖 美国投资最多中国紧随其后 虚拟货币挖矿代码Coinhive入侵联想等近400家网… 普吉沉船后泰旅游业者望对中国免签证费:半年就行 俄运输机或因技术原因在叙坠毁 39人死亡包括一少将 搜狗暂停金融业务 风控能力不足? 张国新代表:建议确认公办中小学教师为教育公务员 哈勒普坦言风大影响发挥 决胜盘1-3后才醒悟 工信部调查WiFi万能钥匙“蹭网” 养20头牛一年赚多少钱 没学历女生做什么工作 如何创业白手起家 在中国发横财七大方法 亚游