Java虚拟机的研究与实现(2)

Java虚拟机的研究与实现(2)

[@more@]

连接又分为三个步骤:验证,准备和解析。验证是对字节码的验证,可根据具体情况来确定被装载的类是否符合Java虚拟机规范中规定的class文件格式,并确保它不会破坏Java虚拟机的完整性。包括(1)类装载过程中的验证; (2) 检查class文件内部的连贯性,一旦发现class文件格式存在一处错误,则抛出VerifyError异常或ClassFormatError异常。确保每个final类不含有子类,final方法不能被覆盖,以及常量池中所有的域引用和方法引用有有效的名字和类型描述符号;(3) 对字节码流使用一个数据流分析器进行验证。准备步骤的任务是创建域表,并设置域初值。解析步骤是将类中的常量池中的类、接口、字段和方法的符号引用替换成直接引用,以达到更快地访问数据的目的。

在初始化阶段,Java虚拟机设计者需要将类变量赋予正确的初始值。

class文件经过上述三个阶段的处理,虚拟机就获得了该类的所有信息并且表示成能够容易操作的内部数据格式,从而为方法的运行作好了充分的准备。

2、及时编译器

任何Java虚拟机实现的核心都是它的执行引擎。在由软件实现的虚拟机中,执行引擎主要有一次性解释字节码、及时编译器、自适应优化编译器三种方式。本实现采用了及时编译的方式,它的特点是第一次被执行的机器码会被编译成本地机器码。及时编译器将引入的字节码翻译成本地机器码,然后直接执行机器码指令而不是解释字节码。机器码指令保存在内存中,由于在运行过程中编译的结果不被保存, 所以程序下一次运行时,字节码将再一次被翻译成机器码。

如果一装载完字节码文件中的Java方法后,就对其进行编译,则有点处理不恰当,因为还不清楚是否需要执行该方法。编译一个不需要执行的方法,将带来不必要的空间和时间上的损失。 因此虚拟机设计者需要采用一种优化方案,即只有需要被执行的方法才能被JIT编译,这个问题可以参照kaffe虚拟机中的trampoline来解决。

JIT实现步骤:(1)对字节码进行验证并且划分基本块;(2)产生四元式;(3)根据四元式生成本地机器码;(4)操作数地址回填。

1151422.jpg498)this.style.width=498;" border="0" />

图3:及时编译器的流程图

在字节码指令模拟操作的时候,按其语义动作生成指令属性四元式序列,指令属性四元式的结构为:(目的操作数,源操作数1,源操作数2,语义动作),四元式数据结构如下:

typedef struct Sequence{

 void (*func)(struct Sequence*); //语义动作

 union{

  jvalue value;

  struct _label_ *labconst; //标号类型操作数

  Method *methconst; //方法地址操作数

  struct slotData **smask;

  struct slotData *slot; //槽操作数

 }u[3];

 uint8 type; //Sequence类型

 uint8 refered; //该四元式的引用

 struct Sequence *next; //下一个四元式

}Sequence;

其中目的操作数为Sequence.u[0],源操作数1为Sequence.u[1],源操作数2为Sequence.u[2]。

Sequence.func则代表语义动作,它主要用于生成该Sequence语义的本地机器码。

指令属性四元组建立后就进入代码生成阶段,属性四元组在形式上已经非常接近本地机器指令,只需要遍历该属性序列,执行相应的语义动作函数,即可生成机器指令。语义动作函数的功能包括操作数寻址、寄存器分配、建立指令连接以及本地机器码生成等。

在及时编译过程中要经常使用到操作数栈,虚拟机把操作数栈作为它的工作区。大多数指令都要从这里弹出数据,执行运算,然后把结果压回操作数栈。而操作数栈区,局部变量区和帧数据区被包含在方法帧中。方法帧的数据结构如下:

typedef struct Frame{

 struct Frame *prev; // 上一帧

 struct Frame *next; // 下一帧

 value_t *sp; // 栈槽指针

 uint8 *pc; // 程序计数器

 method_t *method; //指向正在被执行的方法

 class_t *class_ptr; // 指向包含该方法的类

 value_t locals[1]; //方法的局部变量的起始

}Frame;

本实现中的及时编译器的优点表现在:(1)大大提高了Java应用程序运行的速度;(2)编译过程只在运行时进行,不会改动Java字节码,不会影响Java程序的可移植性;(3)对字节码的编译,使得许多优化手段的采用成为可能。缺点表现在:(1)如果对所有方法进行编译,则会占用大量的内存空间;(2)及时编译的结果在虚拟机终止运行时不被保存,这意味着下一次运行同样的程序仍需要重复编译。

3、垃圾收集

垃圾收集器主要的任务是检测出垃圾对象,然后回收垃圾对象使用的堆空间并还给程序。kaffe采用了增量垃圾收集的算法,而本实现中采用了三色标记并清除算法。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/7839366/viewspace-919817/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/7839366/viewspace-919817/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值