动态链接、方法返回地址、一些附加信息在有些书中会称为侦数据区
基本介绍
动态链接又称为指向运行时常量池方法的引用,每个栈侦内部都会包含一个指向运行时常量池中该栈侦所属方法的引用,即是知道我是谁。
在java源码被编译成字节码文件时,所有的变量和方法引用都作为符号引用保存在class文件的常量池(常量池在方法区中)里,比如 描述一个方法调用了另外的其他方法时,就是通过常量池中指向其他方法的符号引用来表示的,动态链接的作用就是为了将这些符号转为调用方法的实际直接引用。
之所以用常量池,一是能共享常量,不必每份都做存储。
而将符号转为调用方法的实际引用与方法的绑定机制有关,绑定机制分为:
静态链接:如果被调用的目标方法再编译期可知,且运行期间保持不变,则将这个转换过程称为静态链接
静态链接绑定的机制为早期绑定,是由于在编译时期便可知道目标方法的类型,就可以进行绑定
动态链接:如果被调用的目标方法无法在编译器可知,只能够在运行的时候将符号引用转换为直接引用,则称之为动态链接
动态链接绑定的机制为晚期绑定,因为只有在程序运行期间才能根据实际的类型再进行绑定。
早期绑定其实是早期面向过程语言的方式,因为不支持多态性,所以只能实现早期绑定。
下面用代码实际演示一下早期绑定和晚期绑定在字节码中的表现:
package com.lydon.test;
/**
* 说明早起绑定和晚期绑定的例子
*/
public class AnnimalTest {
/**
* 不能在编译时知道动物是猫还是狗,晚期绑定
* @param animal
*/
public void showAnimal(Animal animal){
animal.eat();
}
/**
* 不能在编译时知道捕猎的方式,晚期绑定
* @param hunt
*/
public void showHunt(Huntable hunt){
hunt.hunt();
}
}
class Animal{
public void eat(){
System.out.println("动物进食");
}
}
interface Huntable{
void hunt();
}
class Dog extends Animal implements Huntable{
public void eat(){
System.out.println("狗吃骨头");
}
@Override
public void hunt() {
System.out.println("狗捉耗子,多管闲事");
}
}
class Cat extends Animal implements Huntable{
public Cat(){
super();
}
public Cat(String name){
this();
}
public void eat(){
System.out.println("猫吃老鼠");
}
@Override
public void hunt() {
System.out.println("猫捉老鼠");
}
}
早期绑定:
晚期绑定: