JAVA虚拟机调用一个类方法时,它会基于对象引用的类型(通常在编译时可知)来选择所调用的方法。相反,当虚拟机调用一个实例方法时,它会基于对象实际的类型(只能在运行时得知)来选择所调用的方法,这就是动态绑定,是多态的一种。动态绑定为解决实际的业务问题提供了很大的灵活性,是一种非常优美的机制。

1 JAVA对象模型

JAVA虚拟机规范并没有规定JAVA对象在堆里是如何表示的。对象的内部表示也影响着整个堆以及垃圾收集器的设计,它由虚拟机的实现者决定。

JAVA对象中包含的基本数据由它所属的类及其所有超类声明的实例变量组成。只要有一个对象引用,虚拟机就必须能够快速地定位对象实例的数据。另外,它也必须能通过该对象引用访问相应的类数据(存储于方法区的类型信息),因此在对象中通常会有一个指向方法区的指针。当程序在运行时需要转换某个对象引用为另外一种类型时,虚拟机必须要检查这种转换是否被允许,被转换的对象是否的确是被引用的对象或者它的超类型。当程序在执行instanceof操作时,虚拟机也进行了同样的检查。所以虚拟机都需要查看被引用的对象的类数据。

不管虚拟机的实现使用什么样的对象表示法,很可能每个对象都有一个方法表因为方法表加快了调用实例方法时的效率。但是JAVA虚拟机规范并未要求必须使用方法表,所以并不是所有实现中都会使用它。

下面是一种JAVA对象的内存表示:

JAVA对象内存模型

方法数据存放在类的方法区中,包含一个方法的具体实现的字节码二进制。方法指针直接指向这个方法在内存中的起始位置,通过方法指针就可以找到这个方法。

2 动态绑定内部机制

方法表是一个指向方法区中的方法指针的数组。方法表中不包含static、private等静态绑定的方法,仅仅包含那些需要动态绑定的实例方法。

在方法表中,来自超类的方法出现在来自子类的方法之前,并且排列方法指针的顺序和方法在class文件中出现的顺序相同,这种排列顺序的例外情况是,被子类的方法覆盖的方法出现在超类中该方法第一次出现的地方。

例如有超类Base和子类Derive:

  1. public class Base
  2. {
  3. public Base()
  4. {
  5. }
  6. public void test()
  7. {
  8. System.out.println( "int Base" );
  9. }
  10. public void print()
  11. {
  12. }
  13. }
  14. public class Derive extends Base
  15. {
  16. public Derive()
  17. {
  18. }
  19. public void test()
  20. {
  21. System.out.println( "int Derive" );
  22. }
  23. public void sayHello()
  24. {
  25. }
  26. public static void main( String[] args )
  27. {
  28. Base base = new Derive();
  29. base.test();
  30. }
  31. }

上例中的Base和Derive的方法表如下:

在这个例子里,test()方法在Base和Derive的方法表中都是同一个位置-位置1。在Base方法表中,test()指针是Base的test()方法内存地址;而在Derive方法表中,方法表的位置1放置的是Derive的test()方法内存地址。

当JAVA虚拟机执行base.test()时,通过base引用可以找到base所指向的实际对象的内存位置,现在虚拟机不知道base引用的实际对象是Base还是Derive。但是根据上面的对象内存模型,虚拟机从对象内存中的第一个指针“特殊结构指针”开始,可以找到实际对象的类型数据和Class实例,这样虚拟机就可以知道base引用的实际对象是Derive对。为了执行test(),虚拟机需要找到test()的字节码,方法的字节码存放在方法区中。虚拟机从对象内存中的第一个指针“特殊结构指针”开始,搜寻方法表的位置1,位置1指向的test()方法是Derive类的test()方法,这就是JAVA虚拟机将要执行的test()的字节码。现在,虚拟机知道了调用的实际对象是Derive对象,调用的实际test()方法是Derive类的test()方法,所以JAVA虚拟机能够正确执行-调用base引用的实际对象的方法而不是base引用本身的方法。

这是动态绑定的一种实现方式,根据不同的JAVA虚拟机平台和不同的实际约束,动态绑定可以有不同的内部实现机制

Java动态绑定的内部实现机制的更多相关文章

  1. 转:Java 动态代理的内部实现机制(大体意思正确,写的还行的一篇文章)

    转:Java动态绑定的内部实现机制 JAVA虚拟机调用一个类方法时,它会基于对象引用的类型(通常在编译时可知)来选择所调用的方法.相反,当虚拟机调用一个实例方法时,它会基于对象实际 的类型(只能在运行 ...

  2. 【转】Java学习---HashMap和HashSet的内部工作机制

    [原文]https://www.toutiao.com/i6593863882484220430/ HashMap和HashSet的内部工作机制 HashMap 和 HashSet 内部是如何工作的? ...

  3. java动态绑定的情况分析

    java是面向对象的语言,java中多态的一种情况是动态绑定.所谓的动态绑定,分两种情况:当调用类方法的时候,java虚拟机会基于对象的引用类型来选择执行方法.当java调用一个实例方法的时候,他会根 ...

  4. jvm系列(一):java类的加载机制

    java类的加载机制 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装 ...

  5. HashMap的内部实现机制,Hash是怎样实现的,什么时候ReHash

    1.HashMap的内部实现机制 HashMap是对数据结构中哈希表(Hash Table)的实现,Hash表又叫散列表.Hash表是根据关键码Key来访问其对应的值Value的数据结构,它通过一个映 ...

  6. 深入Java核心 Java中多态的实现机制(1)

    在疯狂java中,多态是这样解释的: 多态:相同类型的变量,调用同一个方法时,呈现出多中不同的行为特征, 这就是多态. 加上下面的解释:(多态四小类:强制的,重载的,参数的和包含的) 同时, 还用人这 ...

  7. java中的动态代理机制

    java中的动态代理机制 在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface).另一个则是 Proxy(Class),这一个类和接口是实现 ...

  8. java基础之 垃圾回收机制

    1. 垃圾回收的意义 在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象:而在Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾.JVM的 ...

  9. java学习笔记09--反射机制

    java学习笔记09--反射机制 什么是反射: 反射是java语言的一个特性,它允许程序在运行时来进行自我检查并且对内部的成员进行操作.例如它允许一个java的类获取他所有的成员变量和方法并且显示出来 ...

随机推荐

  1. ASUS S46CB 刷BIOS

    1. 从ASUS官网下载要新的BIOS文件: 地址:https://www.asus.com.cn/Notebooks_Ultrabooks/S46CB/HelpDesk_Download/ 2. 开 ...

  2. /home 和 /root

    /root     Linux超级权限用户root的家目录./home 如果我们建立一个用户,用户名是"xx",那么在/home目录下就有一个对应的/home/xx路径,用来存放用 ...

  3. 用angular实现$.param()

    首先介绍一下$.param() 功能: 序列化对象或数组,返回字符串 eg: var params = { width:1900, height:1200 }; var str = jQuery.pa ...

  4. css中position中的几个属性

    static  是默认值.任意 position: static; 的元素不会被特殊的定位.一个 static 元素表示它不会被"positioned",一个 position 属 ...

  5. JPA 系列教程21-JPA2.0-@MapKeyColumn

    @MapKeyColumn 用@JoinColumn注解和@MapKeyColumn处理一对多关系 ddl语句 CREATE TABLE `t_employee` ( `id` bigint(20) ...

  6. LWP::UserAgent介绍1

    require LWP::UserAgent; my $ua = LWP::UserAgent->new; ); $ua->env_proxy; my $response = $ua-&g ...

  7. .Net cxy 提高效率

    Visual Studio Visual Studio Productivity Power tool: VS 专业版的效率工具. Web Essentials: 提高开发效率,能够有效的帮助开发人员 ...

  8. js数组对象方法

  9. 12款免费与开源的NoSQL数据库

    Naresh Kumar是位软件工程师与热情的博主,对于编程与新事物拥有极大的兴趣,非常乐于与其他开发者和程序员分享技术上的研究成果.近日,Naresh撰文谈到了12款知名的免费.开源NoSQL数据库 ...

  10. SSM

    今天内容安排 1:复习mybatis 2:复习springMVC 3:springMVC+spring+mybatis组合起来,搭建一个web应用开发的框架 4:用户管理系统,针对用户的CRUD操作, ...