• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Java > JVM 方法调用之动态分派(详解)

JVM 方法调用之动态分派(详解)

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了jvm详解,jvm参数详解,jvm虚拟机详解,jvm方法区,jvm等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

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)");
 }
}
</div>

最终输出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);
  }
</div>

结果将输出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 方法调用之动态分派(详解)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。

</div>
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • JVM的垃圾回收机制详解和调优
  • JVM 方法调用之静态分派(详解)
  • JVM 方法调用之动态分派(详解)
  • JVM 体系结构详解
  • JVM 方法调用之静态分派(详解)
  • JVM 方法调用之动态分派(详解)

相关文章

  • 2017-05-28java 类加载机制和反射详解及实例代码
  • 2017-05-28SpringBoot中自定义注解实现控制器访问次数限制实例
  • 2017-05-28详解Java中hashCode的作用
  • 2017-05-28Java内部类_动力节点Java学院整理
  • 2017-05-28java连接Access数据库的方法
  • 2017-05-28JAVA 运算符归纳总结
  • 2017-05-28Java Web中常用的分页组件(Java端实现)
  • 2017-05-28Struts2之Action接收请求参数和拦截器详解
  • 2017-05-28详解springmvc之json数据交互controller方法返回值为简单类型
  • 2017-05-28Java从网络读取图片并保存至本地实例

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 详解Javascript判断Crontab表达式是否合法
    • Spring MVC配置双数据源实现一个java项目同时连接两个数据库的方法
    • 实例解析JAVA中代码的加载顺序
    • Java使用NioSocket手动实现HTTP服务器
    • Servlet的5种方式实现表单提交(注册小功能),后台获取表单数据实例
    • Java 中 Reference用法详解
    • java Future 接口使用方法详解
    • Spring Hibernate实现分页功能
    • SpringBoot+Shiro学习之密码加密和登录失败次数限制示例
    • springmvc实现json交互-requestBody和responseBody

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有