参考博客:java
【解惑】Java动态绑定机制的内幕:http://blog.csdn.net/zero_295813128/article/details/52117737 程序员
--------------------------------------------------------------------------------------------------数组
下面是本身的理解总结:数据结构
首先得对两个概念有理解方法区和常量池。这两个都是Java虚拟在运行时的数据区域,常量池是方法区ide
的一部分。编码
方法区spa
方法区与Java堆同样,是各个线程共享的内存区域,用于存储已经被虚拟机加载的类信息、常量、静态变
.net
量、即便编译器编译后的代码等数据。线程
常量池指针
常量池是方法区的一部分,用于存放编译期所生成的各类字面量和符号引用。常量池中共有11个常量表。
常量表类型 标志值(占1 byte) 描述
CONSTANT_Utf8 1 UTF-8编码的Unicode字符串
CONSTANT_Integer 3 int类型的字面值
CONSTANT_Float 4 float类型的字面值
CONSTANT_Long 5 long类型的字面值
CONSTANT_Double 6 double类型的字面值
CONSTANT_Class 7 对一个类或接口的符号引用
CONSTANT_String 8 String类型字面值的引用
CONSTANT_Fieldref 9 对一个字段的符号引用
CONSTANT_Methodref 10 对一个类中方法的符号引用
CONSTANT_InterfaceMethodref 11 对一个接口中方法的符号引用
CONSTANT_NameAndType 12 对一个字段或方法的部分符号引用
---------------------------------------------------------------------------------------------------
对于多态的原理主要研究方法区。在Java中多态指的是它容许基类的指针或引用指向派生类的对象,而在具体访
问时实现方法的动态绑定。java中的方法调用有静态绑定和动态绑定之分,静态绑定指的是咱们在编译期就已经
肯定了会执行那个方法的字节码,而动态绑定只有在运行时才能知晓。
静态绑定
Java中的静态方法、私有方法以及final修饰的方法的调用,都属于静态绑定,对于重载的实例方法的
调用,也是采用静态绑定。静态绑定的原理主要是一个常量池解析的过程,下面来详解其过程:
假若有两个类A、B,在A类中咱们调用了B类中的一个静态方法,在编译期,这个调用的动做会被编译成一
条静态调用指令,该指令就对应常量池中的CONSTANT_Methodref表中所存储的该方法的符号引用,经过这个符号引用
能够获得静态方法的全类名B,JVM加载B类,便会获得B类中方法的直接地址,该地址会被存储到A类常量池中对应的
常量表中,这即是常量池解析过程,再次发起调用时,就会直接根据这个直接地址调用对应方法。
以上过程能够看出,在编译阶段咱们就已经肯定了应该执行哪个字节码代码。
动态绑定
动态绑定讲解以前须要了解JVM管理的一个重要的数据结构--方法表。它以数组的形式记录了当前类及其全部
超类的可见方法字节码在内存中的直接地址 。
动态绑定前面的流程与静态绑定相似,假如此处有两个类A,B继承了A类,B类中重写了A类中的f1()方法,咱们采用
向上转型的方式用指向B实例的A类型引用调用f1()方法,编译器会生成一条字节码指令,该指令会去常量表中找到f1()方法信
息的符号引用,经过该引用肯定调用该方法的类型全名,即A类的全名称,根据名称加载到A类的字节码,去A类所对应的方法
表中找到f1()方法,将它的直接地址记录到调用f1()方法的类的对应的常量表中,常量池解析结束,能够思考,咱们此时是否能
肯定调用f1()方法时执行的是哪一块的字节码,答案是不能,由于截至此时咱们f1()方法指定执行的是父类中的方法,引用虽然
父类类型,但他指向的是父类对象仍是子类对象是不知道的(确切地说是此时的程序不知道,程序员确定是知道的),假如指向父类
那就是父类中的f1()方法,若是指向子类的实例,子类没有重写,依然执行父类f1()方法,若是子类重写了就应该是子类的f1()
方法。此时动态绑定就登场了,肯定f1()换须要拿到B类实例在堆中的引用,经过引用找到堆中B的对象,根据对象进一步获取它的
方法表,找到方法表的f1()方法的直接地址,此时便最终肯定了。