您的位置:首页 > 其它

虚拟机字节码执行引擎

2016-07-27 18:41 183 查看
  物理机的执行引擎是由硬件实现的,和物理机的执行过程不同的是虚拟机的执行引擎由于自己实现的。所有的执行引擎的基本一致:输入:字节码文件 处理:字节码解析 输出:执行结果。

运行时栈帧结构

  栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,它是虚拟机运行时数据区中虚拟机栈的栈元素。每个栈帧都包括了一下几部分:局部变量表、操作数栈、动态连接、方法的返回地址和一些额外的附加信息。每一个方法从调用开始到结束的过程都对应着一个栈帧在虚拟机栈里入栈和出栈的过程。栈帧中需要多大的局部变量表和多深的操作数栈在编译代码的过程中已经完全确定,并写入到方法表的Code属性中。因此一个栈帧需要分配多少内存,不会受程序运行时变量数据的影响,仅仅取决于虚拟机的实现。在活动的线程中,位于当前栈顶的栈帧才是有效的,称之为当前帧,与这个栈帧相关联的方法称为当前方法。执行引擎运行的所有字节码指令只针对当前栈帧进行操作。需要注意的是一个栈中能容纳的栈帧是受限,过深的方法调用可能会导致StackOverFlowError,当然,我们可以认为设置栈的大小。其模型示意图大体如下:

public class Dispatch {
static class QQ {
}

static class _360 {
}

public static class Father {
public void harhChoice(QQ arg){
System.out.println("father choose QQ");
}
public void harhChoice(_360 arg){
System.out.println("father choose _360");
}
}
public static class Son extends Father {
public void harhChoice(QQ arg){
System.out.println("son choose QQ");
}
public void harhChoice(_360 arg){
System.out.println("son choose _360");
}
}
public static void main(String[] args) {
Father father=new Father();
Father son=new Son();
father.harhChoice(new _360());
son.harhChoice(new QQ());
}
}


View Code
4.虚拟机动态分配的实现

  动态分派的方法版本选择过程需要运行时在类的方法元数据区中搜索合适的目标方法,因此在虚拟机的实际实现中基于性能考虑,大部分实现都不会真正的进行搜,而是通过在类的方法区建立一个虚方法表,使用虚方法表来代替元数据查找以提高性能。



  虚方法表中存放各个方法的入口。如果某个方法在子类中没有被重写,那子类的虚方法表里的地址入口和父类相同方法的地址入口是一致的,都是指向父类的实现入口。如果子类中重写了这个方法,子类方法表中的地址会替换为指向子类实现版本的入口地址。为了实现方便,具有相同签名的方法,在父类、子类的虚方法表中应当具有相同的索引号,这样当类型变换时便于查找。方法表一般在类加载的连接阶段进行初始化,准备了类的变量初始值后,虚拟机会把该类的方法表也初始化完毕。

基于栈的字节码解释执行引擎

  JAVA编译器输出的指令流基本上是一种基于栈的指令集架构,指令流中的大部分都是零地址指令,它们依赖操作数栈进行工作。基于栈的指令集主要优点是可移植,代码更加紧促、编译器实现更简单,缺点是执行速度相对来说会稍慢一些。

  基于栈的解释执行过程如下:

public int calc(){
int a=100;
int b=200;
int c=300;
return (a+b)*c;
}


  程序字节码如下:



  执行过程如下:









内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: