针对信息设备的Java实时虚拟机

来源:互联网 发布:平面设计网站 知乎 编辑:程序博客网 时间:2024/06/07 07:01

针对信息设备的Java实时虚拟机

Young-Min Lee, Byung-Chul Tak, Hye-Seon Maeng, and Shin-Dug Kim

韩国首尔延世大学计算机科学并行处理实验室

摘要

   通常情况下,嵌入式系统具有较小的内存空间,并且这些系统的应用通常需要实时处理,因此在设计针对嵌入式信息设备的Java虚拟机时要考虑这些限制因素。本论文提出了一些适当的方法将传统Java虚拟机改造为实时Java虚拟机,该虚拟机使嵌入式信息设备能够在苛刻的条件下很好的运行,并且能够满足实时处理的要求。

关键字:Java虚拟机,嵌入式系统,字节码压缩,信息设备

1.引言

      英特网已经得到了广泛的应用,并且还在以指数形式递增,Java正是瞄准了这些在英特网环境下的信息设备应用。尽管Java虚拟机在桌面处理中已经得到了广泛的接受,但是它的初衷确是为了提供一种能够在具有嵌入式微处理器的系统或设备中运行应用软件的环境。这些具有嵌入式微处理器的设备将通过网络进行连接,并且大量新的应用领域将逐步出现。随着手机,个人数字助理,网络电视,甚至电冰箱都装上了微处理器,使得这种目标成为现实。嵌入式系统的功能将不在是一种简单的控制器,应用软件也将变得更加复杂,这些都使得嵌入式系统往往装上高性能的处理器,同时程序员使用高级语言来为嵌入式系统开发应用软件。为了使高级语言适于嵌入式系统应用软件开发,这些高级语言应该容易编码。Java就是这样的一种针对通用信息设备开发应用软件的高级语言。相对于其它的高级语言,它的平台独立性是一个巨大的优势。在Java嵌入式平台上运行Java虚拟机并执行特殊的指令被认为是字节码实现了平台的独立性。用Java语言为嵌入式系统写的应用程序需要嵌入式Java虚拟机和嵌入式Java API的支持。通常嵌入式Java虚拟机具有较小的内存空间,并且它们的应用需要实时处理。为了满足这些要求,本论文提出了一些方法用来实现针对嵌入式信息设备的嵌入式Java虚拟机。

    首先,为了高效利用有限的内存空间,在装载字节码前要进行压缩。自从Java字节码成为一种针对堆栈型机器的固有机器码后,特殊的Java字节码代码块往往重复出现。这种性质使得我们能够找到这些重复的代码块,然后将它们压缩到一种适当的结构中,同时标记这些被压缩的代码块。

    其次,设计一种Java字节码解释器使得对于每一种字节码都有固定的响应时间。一般的Java虚拟机采用开关语句解释每个字节码,这种方式导致每个字节码的处理时间不同。本论文提出了一种方法用来构建一种解释器来克服这种缺点,该方法使用了平台相关的低级语言如汇编语言。

    再次,在虚拟机运行期间,提供一种高效的对象管理方案来为对象分配存储空间。许多现存的Java虚拟机使用哈希结构来加速对象的访问时间,尽管它允许快速访问,但由于大量的哈希表项常处于空闲状态使得内存的利用很低。本文使用链表结构来管理对象,该链表结构通过分割速度来提高内存利用率。

本文余下部分的组织如上所述,第二部分介绍了一些有关Java虚拟机的背景知识,第三部分介绍了字节码压缩技术以及字节码解释器的设计。第四部分给出了模拟结果,同时给出了所用技术的评价。第五部分给出了结论。

 

2.背景知识

    本部分对Java虚拟机和Java编程环境做了简短的描述。

2.1嵌入式Java编程环境

    Java虚拟机是根据Sun微软公司的Java虚拟机规范构建的一种抽象的计算机,该规范详细说明了Java编程语言概念,字节码集和类文件结构。本小节描述了一种嵌入式Java编程环境。

2.1.1 ROM构造器

     ROM映像是将类文件转换成一种能够烧入到ROM中的存储格式的过程。在进行ROM映像前,类文件要通过Java过滤器的筛选和类文件检验器的验证。然后,类文件被类装载器静态的装入到ROM中。ROM构造器引导为Java虚拟机创建ROM映像的整个过程。下面的小节中将解释Java过滤器,类装载器和类文件检验器。

2.1.2  Java过滤器

    Java过滤器检查所属的所有类文件,并提取出用于执行特定的应用程序的类文件。Java程序中的Java类有自己独立的结构,该结构内部具有有机的组织。嵌入式Java虚拟机运行在受限的内存空间中,因而需要提取出这些在特定的程序中需要执行的类。为了容易实现提取特定的类,Java过滤器通过检查类文件中常量池来生成所属类的列表。位于常量池中的CONSTANT_CLASS项给出所属类的信息。

2.1.3 类装载器

    类装载器按预先确定的格式装载位于本地磁盘上的类的文件,类文件的装载格式依赖于Java虚拟机的实现者,对于嵌入式Java虚拟机,实现者应该在其它的标准之上提供最佳的方法用来保护内存。嵌入式Java虚拟机上的类转载器工作于预处理阶段,并将结果永久地保存到ROM中。

2.1.4 类文件检验器

    类检验是在类执行前发现类文件中的错误的过程。基本的类检验包括检查类文件是否符合Java虚拟机规范中规定的标准。在这个过程之后,检验器查找代码中的结构错误。

2.2 Java虚拟机

   1描述了Java虚拟机的结构。

2.2.1 RAMROM

    ROM中的数据固定且不能被修改和删除,ROM中包含类信息,Java虚拟机代码和本地方法。然而,RAM中的数据却是动态的,RAM中存储在执行期间生成和修改的变量。RAM被分成堆,Java栈,PC寄存器和本地方法栈。

2.2.2 解释器

    解释器是Java虚拟机的核心,它负责解码字节码,并解释和执行它们。所有的操作码均具有相同的长度,但是操作数的长度却是不同的。JNI负责维持字节码和本地方法的兼容性。本地方法是和机器相关的,是连接Java程序和主机操作系统的桥梁。当Java方法被调用时,它就调用一个本地方法来执行相关的任务。

2.2.3  JNI

    JNIJava语言的本地编程接口。在特定的主机平台上,它能够使本地方法连接到任何Java虚拟机实现上。使用JNI编写的Java程序具有平台独立性。在一些特殊的应用场合用纯的Java程序无法解决时,程序员就能够书写本地方法来进行处理。当标准的Java类库不足以解决平台相关的问题或者某些优化需要实时处理时,JNI能够使用低级的程序设计语言来直接修改。

2.2.4内存管理器

    内存管理器管理RAM中的堆区域。为了便于垃圾收集,它向垃圾收集器提供了内存的状态。垃圾收集器依次释放那些不再使用的内存。简言之,内存管理器和垃圾收集器协同工作。

2.2.5异常管理器

     Java规范定义了许多异常类,异常管理器就管理这些异常。它检查所有在Java虚拟机规范中定义的错误和异常。用户自己定义的异常也能被创建和使用。

2.2.6线程管理器

     线程管理器负责管理各个线程的时序安排。线程管理可以委派给操作系统,也可以由Java虚拟机实现。这由Java虚拟机的实现者自己决定。每个线程都保存在Java栈的栈帧中,该栈帧描述了它的调用信息。每个栈帧在方法调用时被创建。每次只有位于栈顶的栈帧处于活动状态。当一个线程获得控制权时,位于栈帧中的活动方法接着执行。本地方法的调用将导致将控制权传递给本地方法,当本地方法执行完后,线程就收回控制权。

2.2.7垃圾收集器

垃圾收集器收集不再使用的内存并释放它们以被以后使用。对于垃圾收集有多种实现算法,只有该算法满足嵌入式Java虚拟机实现的要求。

3. 设计嵌入式Java虚拟机

   本节介绍了几种用于实现嵌入式Java虚拟机技术,每种技术都强调内存的最佳使用和解码时间的一致性。

3.1字节码压缩

    Java虚拟机是基于栈结构的机器,因此它不使用通用寄存器来保存中间结果。所有的计算都通过栈来执行,局部变量区被当作寄存器来使用,操作数首先入栈,经过计算后的结果再存入到局部变量中。这就意味着对于相同的计算在计算前后具有相同的代码集。同样在方法调用中也会出现这种情况,方法的参数保存在局部变量区中,当方法被调用时就被压入到栈中,在方法执行完后返回值又会从栈中拷贝到局部变量区中。这种特性使得我们能够对代码进行压缩来提高内存利用率。当然使用代码压缩技术也有其它的原因。

    转移和方法调用使得构造代码块来进行代码压缩不太可能。然而Java程序中很少有绝对转移,条件转移和方法调用,这样就会使得代码的压缩率会很高。表1 显示了SPEC JVM982】中每种指令的代码使用率,SPEC JVM982】被用来衡量JVM运行情况。

    下一节介绍了一种字节码压缩的方法,该方法构建了一种字典结构来存储重复的代码块入口,在程序中只需使用很少的代码指定字典中的索引来引用。

3.1.1 字节码压缩的表示

     一个字节有8位,因此它能够表示256种操作码,但是只有最前面的202种操作码被使用。根据Java虚拟机规范规定,从203228的操作码被定义成快速操作码。在动态加载的过程中,这些快速的操作码将间接引用重定义为一种直接引用。由于没有动态加载机制,嵌入式JVMS不使用这些快速操作码。这些未使用的快速操作码是用来说明字节码压缩的。除了在快速字节码集合中,在其它的地方也可以利用这些未使用的操作码。但这种方式并不推荐,因为当指令被扩展后,它会影响未来的字节码集。快速字节码仅仅能表示有限的条目,因此需要一个字节来做为操作数进行扩展。快速操作码的头25个被用作标记使用在程序中,第26个快速操作码作为代码块的结束标记使用在字典中。这种设计使得在字典中能够表示6400中不同的条目。当JVM运行到快速操作码时,就读取出操作数并根据该操作数计算出实际的代码块地址。代码块以数组的形式存储在字典中,这就要求JVM实现一种算法用于计算出这些特殊条目的入口地址。这些总结了在图1中。

3.1.2代码块的选择和字典的构建

    为了达到最大的压缩比,用于选择被压缩的代码块的算法必须仔细考虑。在本论文中只考虑了一些基本代码块的压缩。基本的代码块不包括条件指令和目标转移指令。对包含有条件指令的代码块进行压缩的压缩过程很复杂,并且还会带来执行期间的额外开销。

    所提出的算法是一个twopass 算法。该算法在第一编扫描代码时,它会选出条件代码,函数调用代码,和目标转移代码,从而区分出基本的代码块。在第二编扫描中,它会将这些基本的代码块添加到哈希表中,并统计出每个代码块的使用频率。哈希表能够快速的判断出一个被选择的代码块是否在该哈希表中。当选择一个代码块作为字典中的一个条目时,它可以按其确切的大小进行存储,或者将其填充到一定的大小进行存储。可变长度的条目有较高的压缩比,但是在执行期间需要找到这些条目的间接引用。在本论文中,根据收集的信息,字典中的最大的代码块被固定到一定的大小,这些被选择的条目就被放在字典结构中。

被选择的代码块被注册到字典中,并被陆续地添加到字典中。字典中的所有条目都包含第26快速操作码,该操作码作为该条目的结束标记。在Java程序中使用两个字节来表示一段代码块已经被压缩到了字典结构中。该两个字节中的第一个字节是快速操作码类中的一种。在执行期间,如果一个快速操作码被检测出,Java解释器必须能够执行一定的操作从字典结构中取得被压缩的代码块并执行该代码块。它保存当前的执行点,改变PC中的值,使其指向被压缩的代码块地址。然后开始执行代码块知道遇到结束标记26_quick字节码。接着它恢复PC中的值并执行其后的代码。下面的伪代码描述了在解释器遇到快速操作码是需执行的操作的算法。

Switch (bytecode)

{

case nop: execute nop

break

case aconst-null: execute aconst-null

break

case iconst-ml: execute iconst-ml

break

.

.

.

case impdep2: execute impdep2

            break

case quick bytecode: save current PC

compute :he dictionary entry

set PC to the dictionary entry

break

case quick: return

bytecode ( 26-quick ) :

restore PC

break

default: Error

break

}

3.2设计解释器

解释器对Java字节码进行译码并执行它们,但一次只执行一条指令。JVM使用开关语句实现译码的过程。它主要的缺点就是不能为每一个操作码提供固定的响应时间,因为它匹配离开关语句远的表达式比离分支语句近的表达式花的时间长。这种性质在实时系统中是不合要求的。因而有三种不同的方法用来克服这种译码时间的不一致性。一种方法是按使用率递减的顺序将字节码放在开关语句中,它提高了解释的过程,而且响应时间保持一样,该方法能够用于通用的JVM中来提高效率。另一种方法是为每一个字节码写一个译码函数,然后使用这些函数指针来译码。这种方法能够为每种字节码提供相同的响应时间,然而该方法却导致了函数调用的额外开销。下面是一个函数指针声明的例子。

Interpreter[bytecodel ( ) ;

最后一种方法就是使用机器相关的语如汇编语言来进行译码。该方法能够提供相同的译码时间,并能够使函数调用的开销最小化。但是使用机器相关的代码使得平台间的移植变得很困难。下面的例子给出了该方法的实现。

target = JMPLENGTH * bytecode;

- asm {

mov eax, offset base

add eax, target

jmp eax

base: jmp nop

jmp aconst-null

             .

             .

             .

jmp impdep2

jmp error

}

nop: execute nop;

goto nextBytecode;

aconst-null: execute aconst-null;

goto nextBytecode;

impdep2: execute impdep2;

goto nextBytecode;

3.3对象管理器

    对象管理器管理由JVM创建的对象,它协调对象间的行为,并提供被请求对象的存取。对象管理器通常使用哈希结构来实现。该结构最主要的优点是能够提供对具体对象的快速访问。SUN公司的JVM使用固定大小的哈希表,通过链表结构来解决冲突问题,图2显示了SUN公司的Java虚拟机使用的对象管理哈希表结构。

对于嵌入式系统,有效的内存管理比执行时间更加关键。哈希结构提供了快速访问,但内存却被浪费了,因为哈希表中的项总是没有完全占用。链表结构消除了内存空间的浪费,并且还有利于垃圾收集。本论文使用链表结构来实现对象管理器。

 

4.实验结果分析

4.1Java字节码压缩

    本小节描述了字节码压缩的结果,所使用的类文件为SUN公司的个人版Java APIKaffe的嵌入式Java API。字典结构中的条目采用固定大小的代码块,以此来减少执行期间的开销。程序中的代码块被两个字节的代码替换。不论该代码块的原始大小是多少,该压缩方法都将代码块都减少到两个字节。由此可得出下面的方程式:

                     G(byte) = (n-2)*m – k

    其中G是字节码压缩的净增益,n是所给的代码块的大小,m是该代码块重复的次数,k是字典中存储该代码块条目的大小。k必须从净增益中减去,因为在程序中消失的代码块(该代码块从程序中移除并被快速操作码取代)在字典结构中占据了k个字节。这个等式表明代码压缩的净增益受字典结构中条目大小的影响。因此字典结构中条目的大小必须被设定为一个合适的大小,从而获得最大的压缩增益。图4和图5显示了使用不同基本代码块大小进行压缩的压缩增益,其中假定每个代码块都能够不改变大小就可以放在字典结构中。

    根据结果显示,当基本代码块的大小在5个到10个字节之间时能够达到最大的压缩比。适当的代码块大小可以选择这个范围内,以发挥最大的性能。压缩比的计算方法也可以使用下面的公式:

compression rate =(original size - compressed size) * 100(%)/(original size);

 

  6和图7显示了在几种不同的字典条目大小上的压缩比。

实验表明,在本论文中提及的压缩方法能够节省约30 %的原始大小。

 

4.2 Java字节码解释器

   本小节的结果是根据在SPEC JVV98上运行的情况获得的。第一种被提及的译码方法是将匹配表达式按发生频率递减的顺序放在开关语句中的。第一个匹配表达式的译码时间和一个条件表达式及一个GOTO语句的执行时间相同。第100个匹配表达式译码时间和100个条件语句及一个GOTO语句的执行时间相同。对于不同的字节码类型执行时间变化很大。使用函数指针的方式译码能够获得统一的译码时间。使用汇编语言实现的译码过程在译码时间上大约提高了50倍。和传统的译码算法比起来,使用函数指针和汇编实现的译码功能在实时系统中表现的非常好,二者都提供了固定的译码时间。表2显示了不同的字节码类的译码时间,图8显示了每种译码算法在SPEC JVM98上运行时的效率。

 

 

 

 

5.结论

    本论文提出了三种方法来提高针对实时嵌入式信息设备的JVM的性能。第一种方法是字节码压缩技术。由于字节码压缩方法不会占据类文件中太多的空间,并且它有较高的压缩比,所以它能使用在具有很少内存空间的嵌入式系统中。再加之它的执行开销很少使得当速度要求较高时非常适合。使用5个字节大小的字典条目来压缩Java API能够使其大小减少到未压缩形式的60%

执行引擎的译码设计的目标就是在实时系统中产生统一的响应时间。因此它能够被应用于嵌入式信息设备和任何其它对实时性能有要求的系统中。使用汇编语言设计的译码算法在译码性能上提高了50倍,该算法能够被用于JVM执行引擎中来提高整体的执行性能。

 

6.引用文献

    [I] James Gosling. Bill Joy, Guy Steel. 7hc Jaua Language Specijlcalion, Addison Wesley, 1996.

[2l SPEC JVM'98, http: //www.spec.org/osg/jv1n98/index.ht1n. l

[3] EnibeddedJavaTM Technical Overview UraJ 1 .Os Sun Microsystems, Inc. 1999.

[4] Tim Lindholm. Frank Yellin, The Java Virtual Machine Specuication Secorirl Edition, Addison Wesley, 1999.

[5] "EmbeddedJava Application Environment Specification." http:/ /Java.sun.com:80/products/embedded,lava/spec/, 1999.

[6] Bill O.Gallriicister, fiogrmuning for the red world POSIX.4, O'REILLY & ASSOCIATES, INC.

[7] Advanced RISC Machines Ltd., An Introduction to Thumb. March, 1995.

[8] T. Bell, J. Cleary, Text Coniprmsion, Prentice IIall, 1990.

[9] P. Bird and T. Mudge, Ari Irislruction Stream Compression Technique, CDE-TR-3 19-96, EECS Department, University of Michigan, November 1996.

 

Young-Min Lee was born in Seoul, Korea. He received the B.S. degreen in computer science from Hansurig IJniversity, Seoul. Korea, in 1998. He received the M.S. degree in computer science from Yonsei University. Seoul, Korea in 2000. His research interests include Java Virtual Machiiie, Internet comuting

    Byung-Chul Tak was horn in Seoul, Korea. He received the B.S. degreen in computer science koni Yonsei University, Seoul, Korea, in 2000, where he is currently pursuing the M.S. degree. His researchinterests include Java virtual machine, web comnuting, parallel processing.

 

 

 

 

 

    Hey-Seon Maeng received the B.S. and M.S.degree in computer science from yonsel University, Seoul.Korea.in 1994 and 1996.respectively. she is currently studing toward Ph.D degree at Yonsel University. Her research intetests include parallel processing. Internet computing Java.

 

 

 

 

 

   Shin-Dug Kim received the B.S. degree in electronic engineering from Yonsel University.Scoul,Korea.in 1982,and the M.S. degree in electrical engineering from the University of Oklahoma in 1987.in 1991,he received the Ph.D. degree at Purde University in computer and electrical engineering.He had been an assistant professor of computer engineering at KwangWoon University,Seoul,Korea from 1992 to 1994. He is currently an associate professor of computer science at Yonsei University,Seoul,Korea. His research interests include parallel system architectures, advanced computer architectures,3D computer graphics,and web computing