




免费预览已结束,剩余74页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
MiniJavaVM一个Java虚拟机的设计和实现摘要本文叙述了Java虚拟机(JVM)的概念及如何设计和实现一个Java虚拟机MiniJavaVM。着重介绍了虚拟机的体系结构及如何设计和实现这个体系结构。在探讨虚拟机的设计过程中详细介绍了MiniJavaVM虚拟机各部分的设计,包括类的装载和解析,内存管理,执行引擎,方法调用和异常处理部分。最后通过测试MiniJavaVM来验证设计和实现的正确性。关键词Java虚拟机(JVM) 字节码 类装载 执行引擎 本地方法MiniJavaVM a design and implementation of a Java Virtual MachineAbstractThis paper describes the conception of Java Virtual Machine (JVM) and how to design and implement a Java Virtual Machine MiniJavaVM. It emphasizes the architecture of JVM and how to design and implement the architecture. It describes the details about each part of JVM when discussing how to design the JVM, including class-loading and resolution, memory management, execution engine, method invoking and exception-handling. At last, the correctness of the design and implementation is validated by testing MiniJavaVM.KeywordsJava Virtual Machine(JVM), byte code, Class-loading, execution engine, Native Method目 录第一章 绪论. 61.1 Java及Java虚拟机. 61.2 Java虚拟机的体系结构. 71.3 MiniJavaVM的功能. 101.4 MiniJavaVM的运行环境及开发工具. 12第二章 系统设计. 132.1 唯一的虚拟机MiniJavaVM. 132.2 MiniJavaVM的构成要素. 132.2.1 虚拟机总体框架. 132.2.2 命令参数解析模块. 152.2.3 类的装载和解析模块. 152.2.4 内存管理模块. 162.2.5 执行引擎模块. 172.2.6 方法调用模块. 182.2.7 异常处理模块. 19第三章 虚拟机框架的实现. 213.1 JVM工程. 223.2 JavaVM工程. 233.2.1 Java虚拟机的数据类型和字长考量. 233.2.2 JavaVM类. 243.3 JavaNativeCall工程. 29第四章 类的装载和解析. 304.1 Java Class文件. 304.2 Class文件在MiniJavaVM中的数据结构表示. 324.3 类的装载和解析. 36第五章 内存管理. 415.1 对象、堆、方法区的管理. 415.2 MiniJavaVM的垃圾回收过程. 44第六章 执行引擎Java操作码实现. 476.1 Java虚拟机中的操作码功能分类. 476.2 操作码功能实现JavaOperatorExecute类. 49第七章 方法调用的实现. 507.1 Java中的方法调用. 507.2 非本地方法的实现. 517.3 本地方法的实现. 527.3.1 Java中的本地方法. 527.3.2 NativeMethod_access类. 547.3.3 如何处理本地方法可变参数问题. 54第八章 异常的实现. 568.1 Java中的异常. 568.2 异常在MiniJavaVM中的实现. 56第九章 验证MiniJavaVM的正确性. 589.1 MiniJavaVM的使用方法. 589.2 测试操作码实现的正确性. 619.2.1 方法调用的正确性. 619.2.2 数学运算的正确性. 649.2.3 控制流语句的正确性. 659.3 测试本地方法调用. 669.4 测试异常处理. 67第十章 不足与后续工作. 6910.1 本地方法. 6910.2 I/O操作. 6910.3 多线程. 6910.4 效率. 69致谢. 71参考文献. 72第一章 绪论1.1 Java及Java虚拟机说起Java,人们首先想到的是Java编程语言,然而事实上,Java是一种技术,它由四方面组成: Java编程语言、Java类文件格式、Java虚拟机和Java应用程序接口(Java API)。它们的关系如下图所示:1 运行期环境代表着Java平台,开发人员编写Java代码(.java文件),然后将之编译成字节码(.class文件)。最后字节码被装入内存,一旦字节码进入虚拟机,它就会被解释器解释执行,或者是被即时代码发生器有选择的转换成机器码执行。从上图也可以看出Java平台由Java虚拟机和Java应用程序接口搭建,Java语言则是进入这个平台的通道,用Java语言编写并编译的程序可以运行在这个平台上。这个平台的结构如下图所示:1 在Java平台的结构中, 可以看出,Java虚拟机(JVM) 处在核心的位置,是程序与底层操作系统和硬件无关的关键。它的下方是移植接口,移植接口由两部分组成:适配器和Java操作系统, 其中依赖于平台的部分称为适配器;JVM 通过移植接口在具体的平台和操作系统上实现;在JVM 的上方是Java的基本类库和扩展类库以及它们的API, 利用Java API编写的应用程序(application) 和小程序(Java applet) 可以在任何Java平台上运行而无需考虑底层平台, 就是因为有Java虚拟机(JVM)实现了程序与操作系统的分离,从而实现了Java 的平台无关性。1什么是Java虚拟机?Java虚拟机是运行所有Java程序的抽象计算机,它仅仅是由一个规范来定义的抽象的计算机。当提及“Java虚拟机”时,可能指的是如下三种不同的东西: 抽象规范 一个具体的实现 一个运行中的虚拟机实例2Java虚拟机负责Java程序设计语言的内存安全、平台无关和安全特性。Java虚拟机屏蔽了与具体操作系统平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机(JVM)在多个平台上实现统一语言。Java之所以得以大行其道,除了它是一门面向对象、构造精美的语言之外,更重要的原因在于:它摆脱了具体机器的束缚,使跨越不同平台编写程序成为可能。1.2 Java虚拟机的体系结构在Java虚拟机规范中,一个虚拟机实例的行为是分别按照子系统、内存区、数据类型以及指令这几个术语来描述的。这些组成部分一起展示了抽象的虚拟机的内部抽象体系结构。但是规范中对它们的定义并非是要强制规定Java虚拟机实现内部的体系结构,更多的是为了严格地定义这些实现的内部特征。规范本身通过定义这些抽象的组成部分以及它们之间的交互,来定义任何Java虚拟机实现都必须遵守的行为。每个JVM都有两种机制,一个是装载具有合适名称的类(类或是接口),叫做类装载子系统;另外的一个负责执行包含在已装载的类或接口中的指令,叫做运行引擎。每个JVM又包括方法区、堆、Java栈、程序计数器和本地方法栈这五个部分,这几个部分和类装载机制与运行引擎机制一起组成了Java虚拟机的体系结构。图1.2.1描述了Java虚拟机的结构框图,包括在规范中描述的主要子系统和内存区。每个Java虚拟机都有一个类装载器子系统,它根据给定的全限定名来装入类型(类或接口)。同样,每个Java虚拟机都有一个执行引擎,它负责执行那些包含在被装载类的方法中的指令。Java虚拟机的运行时数据区存储了许多运行时数据,例如,字节码,从已装载的class文件中得到的其他信息,程序创建的对象,传递给方法的参数,返回值,局部变量,以及运算的中间结果等。Java虚拟机把这些东西都组织到几个“运行时数据区”中,以便于管理。某些运行时数据区是由程序中所有线程共享的,还有一些则只能由一个线程拥有。每个Java虚拟机实例都有一个方法区及一个堆,它们是由该虚拟机实例中所有线程共享的。当虚拟机装载一个class文件时,它会从这个class文件包含的二进制数据中解析类型信息。然后把这些类型信息放到方法区中。当程序运行时,虚拟机会把所有该程序在运行时创建的对象都放到堆中。图1.2.2描述了这些内存区域。当每一个线程被创建时,它都将得到它自己的PC寄存器以及一个Java栈。如果线程正在执行的是一个Java方法(非本地方法),那么PC寄存器的值将总是指示下一条将被执行的指令,而它的Java栈则总是存储该线程中Java方法调用的状态包括它的局部变量,被调用时传进来的参数,它的返回值,以及运算的中间结果等。而本地方法调用的状态,则是以某种依赖于具体实现的方式存储在本地方法栈中,也可能是在寄存器或其他某些与特定实现相关的内存区中。Java栈是由许多栈帧(stack frame)组成的,一个栈帧包含一个Java方法调用的状态。当线程调用一个Java方法时,虚拟机压入一个新的栈帧到该线程的Java栈中;当该方法返回时,这个栈帧被从Java栈中弹出并抛弃。Java虚拟机没有寄存器,其指令集使用Java栈来存储中间数据。这样设计的原因是为了保持Java虚拟机的指令集尽量紧凑,同时也便于Java虚拟机在那些只有很少通用寄存器的平台上实现。另外,Java虚拟机的这种基于栈的体系结构,也有助于运行时某些虚拟机实现的动态编译器和即时编译器的代码优化。图1.2.3描绘了Java虚拟机为每个线程创建的内存区,这些内存区是私有的,任何线程都不能访问另一个线程的PC寄存器或者Java栈。31.3 MiniJavaVM的功能 能够装载并解析java class文件对于已经编译好的java class文件,能够读取该class文件的内容,装载该类,并保存在程序内部的数据结构中。当在程序运行的过程中需要解析该类时,进行解析,并替换符号引用为直接引用 在完成虚拟机的初始化后,能够找到main函数并执行程序13对于指定的入口类,在虚拟机完成了初始化后,寻找该类的main()方法,如果找到,则执行该方法,否则抛出异常,虚拟机运行中止。 支持Java虚拟机规范中规定的200多个操作码的功能实现了Java虚拟机的200多个操作码的功能,由此使MiniJavaVM这个虚拟机模拟Java虚拟机的功能成为可能,这200多个操作码包括: 栈和局部变量操作指令 将常量池入指令 从栈中的局部变量中装载值指令 将栈中的值存入局部变量指令 通用栈操作指令 类型转换指令 整数运算指令 逻辑运算指令 移位操作指令 按位布尔运算指令 浮点运算指令 对象和数组指令 对象操作指令 数组操作指令 控制流指令 条件分支指令 比较指令 无条件转移指令 表跳转指令 异常指令 finally子句指令 方法调用与返回指令 方法调用指令 方法返回指令 线程同步指令 具有内存管理和垃圾收集机制Java虚拟机对内存的管理使得java程序具有很高的安全性,程序员不用担心内存访问越界问题,也不用为在合适的时候释放分配的空间而费心。垃圾收集机制的存在解决何时回收不用的内存和如何回收内存的问题。 支持非本地方法调用按照Java虚拟机规范中的要求来设置非本地方法的调用情况,包括参数压栈,分配局部变量空间,压入方法调用的栈桢等。 支持本地方法调用Java虚拟机中所有与本地方法相关的部分都重新写过,以动态链接库的形式为MiniJavaVM工程提供支持。MiniJavaVM 的本地方法只实现最基本的功能,不再负责虚拟机的安全机制。 支持异常处理有了异常处理,就能够在程序运行时平稳处理意外情况。根据Java class文件中的异常表,MiniJavaVM程序支持所有的异常处理,并在不能解决异常时输出异常信息,虚拟机停止运行。 能够运行与I/O无关的完整Java程序,并提供参数供查看运行效果提供了-version,-showversion,help,-?,verbose 命令。-version命令显示MiniJavaVM的版本信息,然后退出-showversion命令显示MiniJavaVM的版本信息,然后继续运行Java程序-help,-?命令显示帮助信息-verbose命令输出详细数据显示运行过程1.4 MiniJavaVM的运行环境及开发工具开发平台:Windows XP/2003开发语言:ANSI C/C+开发工具:Visual Studio C+/ Visual S运行平台:Windows XP/2000/2003第二章 系统设计2.1 唯一的虚拟机MiniJavaVM一个运行的Java虚拟机实例的天职就是:负责运行一个Java程序。当启动一个Java程序时,一个虚拟机实例也就诞生了。当该程序关闭退出,这个虚拟机实例也就随之消亡。如果在同一台计算机上同时运行三个Java程序,将得到三个Java虚拟机实例。每个Java程序实例都运行于它自己的Java虚拟机实例中。2为此,需要有一种机制保证在运行过程中只有一个Java虚拟机的实例产生。首先要定义表示Java虚拟机的类,然后保证这个类有只一个实例。一种可以供选择的方案是使用Singleton设计模式,保证Java虚拟机实例在整个程序运行过程中只有一个;另一种是可以考虑MFC(Microsoft Fundamental Class)中唯一的全局变量theApp来表示程序运行的实例,通过AfxGetApp()的方法来得到该唯一的全局变量的指针,然后在此基础上进行操作。在这里,我们选择MFC方式定义唯一的全局变量来表示Java虚拟机的运行实例,可以在程序进入main()函数前完成虚拟机的初始化。通过定义一个全局函数来返回虚拟机实例的指针。2.2 MiniJavaVM的构成要素2.2.1 虚拟机总体框架我们的MiniJavaVM的框架合理地组织了虚拟机运行时所需的各模块,将各模块的输入与输出有效地结合在一起,使这些模块组合在一起完成了Java虚拟机的功能。这些模块包括:命令参数解析模块、类的装载和解析模块、内存管理模块、执行引擎模块、方法调用模块、异常处理模块、多线程处理模块(未完成)。我们的MiniJavaVM总的组织方式如图2.2.1所示。其中除命令参数解析模块外,其他模块一起构成了完整的MiniJavaVM虚拟机,这些模块之间协同合作,完成了虚拟机的功能。其中命令参数解析模块负责解析命令,根据MiniJavaVM后的参数来设定虚拟机的运行模式及输出信息;类的装载和解析模块能从class文件或是rt.jar文件中装载指定名称的Java类,并采用迟解析的方式在需要时解析该类,类的信息维护在虚拟机的一个数据结构中;内存管理模块负责为类的实例及静态字段分配空间,并在虚拟机内维护类的实例和静态字段,当虚拟机空间不足时会启动垃圾回收机制来回收内存;执行引擎模块负责解释执行200多个操作码,解释的过程包括对栈桢、栈、PC、 局部变量区的修改;多线程处理模块负责维护虚拟机内的表示线程的数据结构,在语言级提供多线程支持;方法调用模块负责处理方法调用过程,对于非本地方法, 包括找到调用方法的指针,新建栈桢、将方法参数设置在新栈桢的局部变量区,调用方法并将返回值压栈的过程,对于本地方法,包括找到调用方法的指针,将方法 参数用汇编的方式压栈,调用本地方法并将返回值压栈的过程;异常处理模块负责处理虚拟机抛出的异常,记录异常产生处的异常信息,并试图通过查找当前方法的 异常表来处理异常信息,如果能够通过异常表找到处理异常的代码,则修改PC的值使虚拟机处理当前异常,否则,当虚拟机不能处理该异常时,输出异常信息,然后终止虚拟机的运行。通过这几个模块的协同合作,我们的MiniJavaVM虚拟机能够很好地模拟Java虚拟机的功能。2.2.2 命令参数解析模块命令参数解析模块负责解析命令行,根据MiniJavaVM后的参数来设定虚拟机的运行模式及输出信息。该模块的设计如图2.2.2所示:命令参数解析模块在解析完命令行参数后,通过得到虚拟机的唯一实例的指针调用设置参数的方法来设置虚拟机运行时的参数。2.2.3 类的装载和解析模块类的装载和解析模块负责从java class文件或是rt.jar文件中装载指定名称的Java类,并采用迟解析的方式在需要时解析该类,类的信息维护在虚拟机的一个数据结构中。我们的MiniJavaVM类的装载和解析模块设计如图2.2.3所示:其中要装载的类文件有两种渠道获得,一种是直接查找相应类的class文件,一种是从rt.jar文件中得到类的class文件的数据,为了统一这两种方式,可以先从这两种方法中生成类文件的字节流,再交由下一步程序处理。当生成class文件的字节流后,通过指定的模块读取字节流中的信息,生成该Java类在虚拟机中对应的数据。这样,类装载的部分算是完成。在虚拟机运行的过程中,会需要解析类中的常量池,将符号引用替换为直接引用。2.2.4 内存管理模块内存管理模块负责为类的实例及静态字段分配空间,并在虚拟机内维护类的实例和静态字段,当虚拟机空间不足时会启动垃圾回收机制来回收内存。在Java虚 拟机中,关于被装载类型的信息存储在一个逻辑上称为方法区的内存中,所有线程共享方法区,因此它们对方法区数据的访问必须被设计为是线程安全的。方法区的 大小不必是固定的,虚拟机可以根据应用的需要动态调整。同样,方法区也不必是连续的,方法区可以在一个堆(甚至是虚拟机自己的堆)中自由分配。另外,虚拟 机也可以允许用户或者程序员指定方法区的初始大小以及最小和最大尺寸等。4方法区也可以被垃圾收集。因为虚拟机允许用户定义的类装载器来动态扩展Java程序,因此一些类也会成为程序“不再引用”的类。当某个类变为不再被引用的类时,Java虚拟机可以卸载这个类(垃圾收集),从而使方法区占据的内存保持最小。为了简单,我们的MiniJavaVM的方法区使用虚拟机自己的堆,不参与垃圾回收,同时,类的静态字段及一些特殊的类的实例(如与每个类相关的Class类的实例)也不参与垃圾回收。我们的MiniJavaVM内存管理模块设计如图2.2.4所示:当MiniJavaVM虚 拟机请求一个可以被回收的内存空间(比如普通类的实例空间)时,则通过内存管理模块分配可回收的内存,所分配的内存的实地址经过映射后返回给虚拟机,同时 已分配的内存地址记录在一张哈希表中,供快速查找所用。如果虚拟机已经没有可分配的空间,则运行垃圾收集,垃圾收集完成后再分配内存。当虚拟机请求一个不 可被回收的内存空间(比如类的静态字段空间,表示已装载类的Class类的实例等)时,通过内存管理模块分配不可回收内存,所分配的内存的实地址经过映射后返回给虚拟机,同时已分配的内存地址记录在一张哈希表中,供快速查找所用。当垃圾收集完成后仍没有可分配的内存地址可用时,虚拟机退出。2.2.5 执行引擎模块任何Java虚拟机实现的核心都是它的执行引擎。在Java虚拟机规范中,执行引擎的行为使用指令集来定义。对于每条指令,Java虚拟机规范都详细规定了当实现执行到该指令时应该处理什么。5执行引擎模块负责解释执行Java200多个操作码,解释的过程包括对Java栈桢、Java栈、PC、局部变量区的修改。我们的MiniJavaVM执行引擎模块设计如图2.2.5所示:在调用执行引擎模块时,会传入一字节码流,执行引擎模块负责解释这一字节码流。在解释字节码过程中,Java虚拟机可能会装载新的Java类,分配某个Java类的实例,进行数学运算,修改当前java栈桢、Java栈、PC、局部变量区等。2.2.6 方法调用模块方法调用模块负责处理方法调用过程,对于非本地方法,包括找到调用方法的指针,新建栈桢、将方法参数设置在新栈桢的局部变量区,调用方法并将返回值压栈的过程,对于本地方法,包括找到调用方法的指针,将方法参数用汇编的方式压栈,调用本地方法并将返回值压栈的过程。我们的MiniJavaVM方法调用模块的设计如图2.2.6所示:虚拟机为每一个调用的Java(非本地)方法一个新的栈帧。栈帧包括:为方法的局部变量所预留的空间,该方法的操作数栈,以及特定虚拟机实现需要的其他所有信息。局部变量和操作数栈的大小在编译时计算出来,并放置到class文件中去,然后虚拟机就能够了解到方法的栈帧需要多少内存。当虚拟机调用一个方法的时候,它为该方法创建恰当大小的栈帧,再将新的栈帧压入Java栈。处理实例方法时,虚拟机从所调用方法栈帧内的操作数栈中弹出objectref和args。虚拟机把objectref作为全局变量0放到新的栈帧中,把所有的args作为局部变量1,2,等处理。Objectref是隐式传给所有实例方法的this指针。对于类方法,虚拟机只从所调用的方法栈帧中的操作数栈中弹出参数,并将它们放到新的栈帧中去作为局部变量0,1,2当objectref和args(对于类方法则只有args)被赋给新栈帧中的局部变量后,虚拟机把新的栈帧作为当前栈帧,然后将程序计数器指向新方法的第一条指令。6虚拟机使用一种“与实现相关”的风格调用本地方法。当调用本地方法时,虚拟机不会将一个新的栈帧压入Java栈。当线程进入到本地方法的那一刻,它就将Java栈抛在身后。直到本地方法返回以后,Java栈才被重新调用。这里本虚拟机的实现将使用调用动态链接库中的方法来实现本地方法调用的过程。2.2.7 异常处理模块异常处理模块负责处理虚拟机抛出的异常,记录异常产生处的异常信息,并试图通过查找当前方法的异常表来处理异常信息,如果能够通过异常表找到处理异常的代码,则修改PC的值使虚拟机处理当前异常,否则,当虚拟机不能处理该异常时,输出异常信息,然后终止虚拟机的运行。我们的MiniJavaVM异常处理模块的设计如图2.2.7所示:第三章 虚拟机框架的实现Java虚拟机的体系结构如图3.1所示:实现虚拟机框架,需要考虑以下几点: 虚拟机的数据类型和字长 如何实现栈结构 如何装载和解析类 如何调用本地和非本地方法 如何实现执行引擎 如何实现多线程 机如何组织方法区和堆 如何进行垃圾回收 虚拟机如何处理异常为了解决这些问题,这里我们把MiniJavaVM虚拟机的实现总体分为三部分。第一部分为主体部分,JavaVM工程。这个工程相当于实现了一个Java虚拟机的所有功能,包括定义虚拟机的数据类型和字长,实现虚拟机栈结构,组织方法区和堆,装载和解析类,实现执行引擎,调用非本地方法,实现多线程,处理异常等。但这个工程不负责虚拟机在执行过程中需要调用的本地方法的实现。由于本地方法总是与Java虚拟机实现的底层平台相关的,因此这个工程只负责处理与底层平台实现不相关的部分,而将与底层平台实现相关的部分交给另外一个工程JavaNativeCall工程。JavaVM工程将开发为动态链接库的形式,有利于别的工程调用这个工程中重要的导出类和导出方法。第二部分为本地方法实现部分,JavaNativeCall工程。此工程负责本地方法接口(JNI)的声明和实现。该工程将开发为动态链接库的形式,有利于JavaVM工程调用该工程中的导出函数。第三部分为主程序,JVM工程。该工程负责解析并设置虚拟机运行参数,调用JavaVM工程的虚拟机实现类来启动虚拟机。该工程为可执行文件。我们将主程序与虚拟机工程分离,底层平台实现相关与实现无关部分代码分离,使MiniJavaVM虚拟机的实现更具层次感。同时,也具有了更好的可扩充性3.1 JVM工程JVM工程负责解析并设置虚拟机运行参数,调用JavaVM工程的虚拟机实现类来启动虚拟机。JVM工程所要完成的任务可以用图3.1.1表示:JVM工程只是调用JavaVM工程中导出的JavaVM类,设置其参数及入口类,所有Java虚拟机的运行工程交由JavaVM类完成。3.2 JavaVM工程JavaVM工程实现了一个Java虚拟机的所有功能,包括定义虚拟机的数据类型和字长,实现虚拟机栈结构,组织方法区和堆,装载和解析类,实现执行引擎,调用非本地方法,实现多线程,处理异常等。但这个工程不负责虚拟机在执行过程中需要调用的本地方法的实现。由于本地方法总是与Java虚拟机实现的底层平台相关的,因此这个工程只负责处理与底层平台实现不相关的部分,而将与底层平台实现相关的部分交给另外一个工程JavaNativeCall工程。3.2.1 Java虚拟机的数据类型和字长考量Java虚拟机是通过某些数据类型来执行计算的,数据类型及其运算都是由Java虚拟机规范严格定义的。数据类型可以分为两种:基本类型和引用类型。基本类型的变量持有原始值,而引用类型的变量持有引用值,图3.2.1描述了Java虚拟机中的数据类型:Java虚拟机规范定义了每一种数据类型的取值范围,但是没有定义它们的位宽。存储这些类型的值所需的占位宽度,是由具体的虚拟机实现的设计者决定的。Java语言中的所有基本类型同样也是Java虚拟机中的基本类型。但boolean有点特别,当编译器把Java源码编译为字节码时,它会用int或byte来表示boolean。在Java虚拟机中,false是由整数零来表示的,所有非零整数都表示true。涉及boolean值的操作则会使用int。表3.2.1 Java虚拟机数据类型的取值范围类型范围Byte8比特,带符号,二进制补码Short16比特,带符号,二进制补码Int32比特,带符号,二进制补码Long64比特,带符号,二进制补码Char16比特,不带符号,Unicode字符Float32比特,IEEE754标准单精度浮点数Double64比特,IEEE754标准单精度浮点数ReturnAddress同一方法中某操作码的地址Reference堆中对某对象的引用,或者是nullJava虚拟机中,最基本的数据单元就是字(word),它的大小是由每个虚拟机实现的设计者来决定的。字长必须足够大,至少是一个字单元就足以持有byte、short、int、char、float、returnAddress或者reference类型的值,而两个字单元就足以持有long或者double类型的值。因此,虚拟机实现的设计者至少得选择32位作为字长,或者选择更为高效的字长大小。通常根据底层主机平台的指针长度来选择字长。Java虚拟机规范中,关于运行时数据区的大部分内容,都是基于“字”这个抽象概念的。比如,关于栈帧的两个部分局部变量和操作数栈都是按照“字”来定义的。这个内容区域能够容纳任何虚拟机数据类型的值,当把这些值放到局部变量或者操作数栈中时,它将占用一个或两个字单元。7在我们的JavaVM工程中,对Java虚拟机的数据类型和字长的定义如下:3.2.2 JavaVM类JavaVM类是JavaVM工程中最重要的一个类,这个类定义了Java虚拟机应该实现的功能,所有Java虚拟机相关的功能对应于通过调用该类的相应方法来实现。为了定义JavaVM类,我们必须定义其他一些辅助类。这些辅助类包括:JavaThread类:负责管理虚拟机线程CClassFile类:负责读取Java Class文件的内容JavaClassInfo类:负责根据CClassFile类的内容生成该java类的类信息JavaArrayInfo类:负责生成某一类型的数组信息JavaClassFileLoader类:负责找出要装载的java class文件,并将文件内容作为二进制流传给CClassFile类Cp_xxxxxxxx类:负责维护Class文件中常量池的内容Attr_xxxxxxxx类:负责维护Class文件常量池中attr_info相关的内容Memxxxxxxx类:负责虚拟机的内存管理,包括分配内存和进行垃圾收集JavaVM类的接口定义如下:我们的JavaVM类内部组织如图3.2.3所示:其中线程部分设计如图3.2.4所示:通过上面设计,使用JavaVM类来表示Java虚拟机,使用一个唯一的JavaVM的全局变量来代表运行中的Java虚拟机;使用链表来存储在Java虚拟机上运行的所有线程,并保留一个指向当前线程的指针;使用链表来存储已经装载的class文件的信息,并保留一个指向入口class的指针,以找到正确的main()入口;在JavaVM类中定义内存管理模块的接口,通过调用这些接口来分配并读写内存,并把类信息同相应的返回的引用值联系起来;在JavaVM类中定义垃圾收集模块的接口,通过这些接口来进行垃圾收集。3.3 JavaNativeCall工程JavaNativeCall工程为本地方法实现部分工程。此工程负责本地方法接口(JNI)的声明和实现。该工程开发为动态链接库的形式,有利于JavaVM工程调用该工程中的导出函数,真正做到本地方法调用的功能。为了实现这个工程,这里参考了Kaffe中关于JNI实现部分的代码。Kaffe是一个功能强大的Java虚拟机,它包括Java2 平台的子集,标准Java API和工具来提供Java运行时环境。12MiniJavaVM的本地方法接口(JNI)部分主要是参考了Kaffe中对本地方法接口的定义。我们的MiniJavaVM的本地方法接口的实现定义了如下类型:所有JNI函数的声明均按照“_MiniJavaVM+包名类名方法名参数列表”的格式声明。如java.lang.System类的本地方法registerNatives()的声明如下:java_void _MiniJava_java_lang_System_registerNatives(JavaVM* pJVM,java_class clsref);具体调用时,只要在装载该方法所在的动态链接库后再得到该方法的地址,将参数压栈,调用这个方法,就能完成这个方法的调用,也就实现了Java本地方法。第四章 类的装载和解析4.1 Java Class文件Java class文件中包含了Java虚拟机所需知道的、关于类或接口的所有信息。Java class文件是8位字节的二进制流。数据项按顺序存储在class文件中,相邻的项之间没有任何间隔,这样可以使class文件更紧凑。占据多个字节空间的项按照高位在前的顺序分为几个连续的字节存放。8和Java类的可以包含多个不同的字段、方法、方法参数、局部变量等一样,Java class文件也能够包含许多不同大小的项。在class文件中,可变长度项的大小和长度位于其实际数据之前。这个特性使得class文件流可以从头到尾被顺序解析,首先读出项的大小,然后读出项的数据。Class文件的基本类型如下,所有存储在u2,u4,u8项中的值,在class文件中以高位在前的形式出现。表4.1.1 class文件“基本类型”u11个字节,无符号类型u22个字节,无符号类型u44个字节,无符号类型u88个字节,无符号类型可变长度的ClassFile表中的项,如表4.1.2所示:表4.1.2 ClassFile表的格式类型名称数量U4Magic1U2Minor_version1U2Major_version1U2Constant_pool_count1Cp_infoConstant_poolConstant_pool_count-1U2Access_flags1U2This_class1U2Super_class1U2Interfaces_count1U2InterfacesInterfaces_countU2Fields_count1Field_infoFieldsFields_countU2Methods_count1Method_infoMethodsMethods_countU2Attributes_count1Attribute_infoAttributesAttributes_countJava Class文件中的常量池包括了与文件中类和接口相关的常量,其中存储了诸如文字字符串、final变量值、类名和方法名的常量。常量池中的许多入口都指向其他的常量池入口,而且class文件中紧随着常量池的许多条目也会指向常量池中的入口在整个class文件中,指示常量池入口在常量池列表中位置的整数索引都指向这些常量池入口。列表中的第一项索引值为1,第二项索引值为2,以此类推。尽管constant_pool列表中没有索引值为0的入口,但缺失的这一入口也被constant_pool_count计数在内。第个常量池入口都从一个长度为一个字节的标志开始,这个标志指出了列表中该位置的常量类型,一旦Java虚拟机获取并解析这个标志,Java虚拟机就会知道在标志后的常量类型是什么。表4.1.3列出了所有常量池标志的名字和值。表4.1.3 常量池标志入口类型标志值描述CONSTANT_Utf81UTF-8编码的Unicode字符串CONSTANT_Integer3Int类型字面值CONSTANT_Float4Float类型字面值CONSTANT_Long5Long类型字面值CONSTANT_Double6Double类型字面值CONSTANT_Class7对一个类或接口的符号引用CONSTANT_String8String类型字面值CONSTANT_Fieldref9对一个字段的符号引用CONSTANT_Methodref10对一个类中声明的方法的符号引用CONSTANT_InterfaceMethodref11对一个接口中声明的方法的符号引用CONSTANT_NameAndType12对一个字段或方法的部分符号引用在类或者接口中声明的每一个字段(类变量或者实例变量)都由class文件中的一个名为field_info的可变长度的表进行描述。在一个class文件中,不会存在两个具有相同名字和描述的字段。表field_info的格式如下表4.1.4 field_info表的格式类型名称数量U2Access_flags1U2Name_index1U2Descriptor_index1U2Attributes_count1Attribute_infoAttributesAttributes_count在class文件中,每个在类和接口中声明的方法,或者由编译器产生的方法,都由一个可变长度的method_info来描述。同一个类中不能存在两个名字及描述符完全相同的方法。有可能在class文件中出现的两种编译器产生的方法是:实例初始化方法(名为)和类与接口初始化方法(名为)。Method_info表的格式如下:表4.1.5 method_info表的格式类型名称数量U2Access_flags1U2Name_index1U2Descriptor_index1U2Attributes_count1Attributes_infoAttributesAttributes_count属性在Java class文件中多处出现。它们可以出现在ClassFile、field_info、method_info和Code_attribute表中。Java虚拟机规范定义了9种属性,为了正确解释Java class文件,所有Java虚拟机实现都必须能够识别下列三种属性:Code,ConstatValue和Exception。为了正确地实现Java和Java2平台,虚拟机实现必须能够识别InnerClasses和Synthetic属性,但可以自主选择空间是识别还是忽略其他一些预定义的属性。由规范定义的attribute_info表的属性如下表:表4.1.6 由规范定义的attribute_info表的类型名称使用者描述CodeMethod_info方法的字节码和其他数据ConstantValueField_infoFianl变量的值DeprecatedField_info、method_info字段或者方法被禁用的指示符ExceptionsMethod_info方法可能抛出的可被检测的异常InnerClassesClassFile内部、外部类的列表LineNumberTableCode_attribute方法的行号与字节码的映射LocalVariableTableCode_attribute方法的局部变量的描述SourceFileClassFile源文件名SyntheticField_info、method_info编译器产生的字段或者方法的指示符4.2 Class文件在MiniJavaVM中的数据结构表示JavaVM工程的CClassFile类负责读取java Class文件的内容,将class文件的二进制表示形式保存为虚拟机可以理解的数据结构。CClassFile类的设计如图4.2.1所示:对于CClassFile类,最重要的就是读取指定Java类名的class文件,这个最重要的任务交给ReadClassFile()方法做。这个方法实现了三个功能:首先,找到该java类的class文件或是从rt.jar文件中找到该java类的class文件,读取这个类文件的二进制数据,并提交下一步处理;第二,根据二进制数据填充ClassFile类中的变量,这些变量的定义与ClassFile表一致;最后,根据ClassFile类的变量整理出类的信息,填充到新的结构JavaClassInfo中。Execute()函数对于入口class有用,通过调用该class文件的Execute()函数,Java虚拟机能从这个函数的main()函数开始执行。ClassFile类的变量定义如图4.2.2所示:Class文件常量池数据结构设计如下,所有的11种常量池表示类均从一个父类继承,并通过调用父类的静态成员函数GenerateCPInfo()来生成某一特殊类型的常量池:在cp_info的静态成员函数GenerateCPInfo()中,先通过读取第一个字节来得知这个常量池的类型,然后根据这个类型来生成11个常量池类型中的一种,其类型值在m_nTag中保存,并返回它的指针(统一为cp_info的指针在ClassFile类中保存)。当要使用常量池中的某一值时
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 汉字的六种结构方式
- 2025-2026年北京市中考英语综合提高练习试卷4
- 高端消费品市场需求研究
- 2025年国际劳动合同范本下载
- 水质标准基本知识培训课件
- 酒店网络安全方案
- 智算中心虚拟化平台部署与管理方案
- 混凝土运输途中振动控制方案
- 输电线路隐患排查与整改方案
- 建筑工程施工中污染控制与治理方案
- 乡镇道路清扫合同范例
- DB3209T 1232-2023 菊花病虫害绿色防控技术规程
- 员工应聘登记表(齐全版)
- 手术室停电停水应急预案
- 人教版初中八年级数学上册《第十一章 三角形》大单元整体教学设计
- 《高级统计实务和案例分析》和考试大纲
- 韦莱韬悦-东方明珠新媒体集团一体化职位职级体系方案-2018
- 2024新版(外研版三起孙有中)三年级英语上册单词带音标
- 注塑缺陷的原因分析与解决对策培训教程
- 中欧班列课件
- 2025年九省联考新高考 物理试卷(含答案解析)
评论
0/150
提交评论