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. [帖子收集]通用Windows平台(UWP)

    通用Windows平台,universal windows platform,UWP 什么是通用 Windows 平台 (UWP) 应用?(微软MSDN) 如何在通用 Windows 平台应用中使用现 ...

  2. servlet就实现在线用户表

    在学习servlet的过程中,学习了如何用servlet实现在线用户表. 只有服务器处于开机状态才会有在线用户表的存在,在服务器关机的情况下自然就不存在在线用户表的说法:所以,楼主认为在线用户表的信息 ...

  3. Framebuffer的配置及应用——先转载留着,以后一定要弄懂

    http://blog.csdn.net/tju355/article/details/6881389   借助于framebuffer,我们能够在console下面作很多事情.首先下载framebu ...

  4. POJ - 1330 Nearest Common Ancestors(基础LCA)

    POJ - 1330 Nearest Common Ancestors Time Limit: 1000MS   Memory Limit: 10000KB   64bit IO Format: %l ...

  5. javascript Navigator对象

    0.Navigator 对象包含有关浏览器的信息,通常用于检测浏览器与操作系统的版本. 1.对象属性 2. var browser=navigator.appName; var b_version=n ...

  6. 使用java写一个小白计算器

    有点小意思~ package ok; import java.awt.BorderLayout; import java.awt.Color; import java.awt.GridLayout; ...

  7. gulp4个基础API

    Gulp.src(globs[, options]) 此接口会匹配工作目录下指定规则的文件并返回提供给下一个插件管道使用.其中globs就是匹配格式,options是一些额外参数. gulp.src( ...

  8. NYIST OJ 题目20 吝啬的王国

    DFS水题.题意说明了这是一颗树,那么只要按照根节点DFS下去就好了,DFS的时候记录一下当前在哪个结点,还有父节点是谁,就AC了! #include<cstdio> #include&l ...

  9. MYSQL导入中文数据乱码的四种解决办法

    方法一:通过增加参数 --default-character-set = utf8 解决乱码问题 方法一:通过增加参数 --default-character-set = utf8 解决乱码问题 my ...

  10. bootstrip 折叠菜单

    body { font-family: "宋体"; font-size: 12px } .menu { height: 30px; background: #e6e6e6; mar ...