(计算机系统结构专业论文)基于龙芯处理器的java运行环境的移植与优化.pdf_第1页
(计算机系统结构专业论文)基于龙芯处理器的java运行环境的移植与优化.pdf_第2页
(计算机系统结构专业论文)基于龙芯处理器的java运行环境的移植与优化.pdf_第3页
(计算机系统结构专业论文)基于龙芯处理器的java运行环境的移植与优化.pdf_第4页
(计算机系统结构专业论文)基于龙芯处理器的java运行环境的移植与优化.pdf_第5页
已阅读5页,还剩54页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

摘要 研发我国自主的高性能处理器芯片在经济和国家安全方面具有重要意义,龙 芯系列处理器的成功研制填补了我国自主高性能通用处理器的空白。龙芯的一个 重要应用方向是企业服务器,在企业服务应用上目前j a v 棚2 e e 独占鏊头。很多 大型软件如m o z i l l a 、o p e n o f f i c e 等也依赖于j a v a 虚拟机。但是在我们的工作之前 尚无支持龙芯处理器的完整的j a v a 运行环境。为龙芯处理器开发个高效的j a v a 运行环境对龙芯的发展十分重要。 本文以开发在龙芯处理器上运行的高性能的j a v a 运行环境为目的,研究了 与j a v a 虚拟机相关的j a v a 虚拟机规范、字节码解释器、j i t 编译器以及垃圾收 集器等各种理论和技术,分析并比较了k a f f e 、j i k e sr v m 、h o t s p o t 等多种流行 的j a v a 虚拟机的结构及其优缺点。将s u nj d k ( j a v ad e v e l o p m e n tr a t ) 1 5 ( 包括相 应的h o t s p o tj a v a 虚拟机) 移植到了龙芯2 号上。在以上工作的基础上进行了 h o t s p o t 服务器版虚拟机的移植。由于服务器程序的特殊行为,它们不适合运行 在桌面应用的j a v a 虚拟机上,s u nj d k 为此单独包括了一个服务器版的j a v a 虚 拟机,其实现了更为强大的j i t 编译器。 此外,本文还分析了完成移植的h o t s p o t j a v a 虚拟机在龙芯2 号样机上运行 的性能问题并与x 8 6 版本作出比较。在以上工作基础上做了寄存器优化、t h r e a d 指针优化、数组越界检查优化等优化工作,并给出了相应的分析。 关键词:j a v a ,龙芯二号,h o t s p o tj a v a 虚拟机,垃圾收集,j 盯 、 p o r ta n do p t i m i z a t i o no fj a v av i r t u a lm a c h i n eo ng o d s o n h a v i n go u ro w nh i g h p e r f o r m a n c ep r o c e s s o ri sv e r yi m p o r t a n tf o rc h i n a g o d s o ns e r i e sp r o c e s s o r sa r et h ef i r s ts e l f - d e p e n d e n tg e n e r a lp r o c e s s o r si no u r c o u n t r y , a n da so n eo ft h e m g o d s o ni ii so n eo ft h ef i r s t - c l a s sp r o c e s s o r si nt h ew o r l d n o w o n eo ft h em o s ti m p o r t a n ta p p l i c a t i o n so fg o d s o ni st or u ne n t e r p r i s e a p p l i c a t i o n s j a v a j 2 e e i st h em o s tp o p u l a rd e v e l o p m e n tt o o lf o r e n t e r p r i s e a p p l i c a t i o n s s o m es o f t w a r e ss u c ha sm o z i l l a ,o p e n o f f i c ed e p e n do nj a v a i t s i m p o r t a n tt od e v e l o paj a v av i r t u a lm a c h i n ef o rg o d s o n i nt h i sp a p e r ,w ei n v e s t i g a t et e e h n o l e l g i 髓c o n c e r n e dw i t h j a v av i r t u a lm a c h i n e , s u c ha st h ej v ms t a n d a r d ,i n t e r p r e t e r , j i tc o m p i l e r , g a r b a g ec o l l e c t i o n ,a n ds oo n w e a n a l y s et h ea d v a n t a g e sa n dd i s a d v a n t a g e so fs e v e r a lp o p u l a rj a v av i r t u a lm a c h i n e p r o j e c t s ,a n dp o r ts u nj d k ( j a v ad e v e l o p m e n tk i t ) 1 5t og o d s o n w ea n a l y s et h ep e r f o r m a n c eo ft h eh o t s p o to ng o d s o n 2 ,c o m p a r e dt ot h ex 8 6 v e r s i o n s o m eo p t i m i z a t i o n ss u c ha sg e t _ t h r e a da n dr a n g e e h e c ka r ed o n ef o rg o d s o n k e y w o r d s :j a v a ,g o d s o ni i ,h o t s p o t ,j v m ,g a r b a g ec o l l e c t i o n , j i t n 图目录 圈2 1j a v a 运行环境示意图 图2 2 两种解释器结构示意图。 ! ; 1 1 图2 3j i t 编译过程 | 璺i3 1 三种虚拟机运行j v m 9 8 程序时间比较 图3 2 三种虚拟机运行j b b 2 0 0 0 分值比较 i 璺l4 , 1j a v a 对象模型。 图4 2h o t s p o t 线程继承关系图 图4 3 解释器结构示意图 图4 4 解释栈帧示意图 图4 5h o t s p o t 垃圾收集器示意图 图4 6 年轻代布局示意图 图5 1j v m 9 8 程序时间执行g e l t h r e a d 次数统计 图5 2g e t _ t h r e a d 优化在j v m 9 8 上的效果 图5 , 3j v m 9 8 中数组越界检查次数。 图5 4 数组越界检查优化在j v m 9 8 上的效果 图6 1j v m 9 8 测试程序中执行s w a p 次数统计 图6 2j v m 9 8 测试程序中执行c m p x c h g 次数统计 图6 3j v m 9 8 在x 8 6 版本上运行性能 图6 4j v m 9 8 在龙芯2 e 上运行性能 图6 5 j v m 9 8 在龙芯2 e 上运行性能 图6 5x 8 6 上j r r 编译各个阶段时间比例 图6 6 龙芯上j | t 编译各阶段时间比例 v 4 5 4 6 4 8 4 8 4 9 5 0 5 l 5 2 5 2 加殂筋凹勉拇柏钙 第一章引言 1 课题背景 第一章引言 j a v a 语言1 2 】作为新一代的面向对象语言自诞生以来就因其跨平台、安全性、 动态运行、自动内存管理等特性在多种领域获得了广泛的应用。近年来由于j 2 e e 的发展,j a v a 语言已经在企业应用开发界成为主流。使用j a v a 开发或者部分开 发的应用程序( 包括大型软件) 越来越多见,如永中o f f i c e 、e c l i p s ei d e 、l u m a q q 等。j a v a a p p l e t 在b s 结构的应用上也十分常见,这使得j a v a 虚拟机【3 】成为 m o z i l l a 、f i r e f o x 之类的网络浏览器的必需组件。随着l i n u x 操作系统占据了更大 的市场,j a v a 也逐渐成为l i n u x 应用及跨平台应用的首选图形界面开发工具,如 o r a c l e 数据库等。为龙芯处理器开发一个高效的j a v a 虚拟机是十分重要和必需 的。 j a v a 语言在具有上述的大量优点的同时也带来了j a v a 程序运行效率低的缺 点,这主要是由于字节码的执行速度较慢、自动内存管理带来的时空开销、动态 运行方式( 虚方法、接口和类载入) 的运行时开销且难以优化以及大量的同步开 销等。 j a v a 运行环境是一个十分庞大的系统,其中最为关键的部分是j a v a 虚拟机, 它是执行j a v a 程序的核心部件,它必须解决j a v a 程序运行效率低的缺点为了 让龙芯处理器能够运行j a v a 程序,首要工作就是移植一个完整的兼容于标准的 j a v a 虚拟机,这涉及到与j a v a 虚拟机相关的诸如虚拟机规范、字节码解释器、 j i t 编译器、垃圾收集器以及编译等理论和技术。其次,需要针对龙芯处理器系 统结构的特点对这个虚拟机做优化工作,使得j a v a 程序可以在龙芯处理器上高 效运行。 2 j a v a 相关技术简介 j a v a 是s u n 开发的新一代面向对象语言【2 】,它的跨平台、安全性、动态运 行、自动内存管理以及对网络和多线程开发的良好支持使得它成为目前最流行的 开发语言之一。 不同于c 等传统的编程语言,j a v a 源代码( j a v a 文件) 被j a v a 编译器编译 成平台无关的j a v a 字节码存放在c l a s s 文件中,由具体平台上实现的j a v a 虚拟机 运行【3 】。j a v a 字节码是实现j a v a 跨平台的关键,它实际上是一种加入了面向对 象支持的栈式机器语言。j a v a 字节码无法像可执行文件一样直接在硬件上运行, 筚于龙芯处理器的j a v a 运行环境的移植与优化 它需要一个由字节码到本地指令转换的过程( b r i d g e ) ,这就是j a v a 虚拟机的功 能。字节码执行方式主要有四种,分别是解释执行、翻译执行、编译执行( j l t , j u s t - i n t i m ec o m p i l e ) 和硬件执行。解释执行效率最低,翻译执行消除了执行两 个字节码指令之间的跳转,编译执行则进一步减少了冗余操作、消除了栈操作并 做了一些优化。由于j a v a 字节码中加入了对面向对象的支持,硬件执行会导致 硬件代价过大,大多数实现是采用软硬件结合的方式,在实际中应用的并不多。 j a v a 的另外一个主要特性是自动内存管理。j a v a 程序员无须明确释放不再使 用的对象所占用的内存,它们由虚拟机自动发现并释放,这一功能由垃圾收集器 提供。不同于c + + 等面向对象语言,j a v a 中所有对象都是存放在堆中的,都是动 态分配的;j a v a 栈中只有基本类型和引用类型( 可以视为对象指针) 数据。垃圾 收集可以由程序明确调用释放内存或者在分配对象失败时由虚拟机调用。垃圾收 集过程简单的描述就是从根集出发找到存活对象并将从根集不可达的对象视为 垃圾并释放的过程。经典的垃圾收集算法有引用记数、标记清扫、标记压缩、节 点复制等。垃圾收集时需要遍历堆,这是十分大的开销,为了减少这个开销出现 了分代式垃圾收集算法和渐近式垃圾收集算法;为了利用多处理器资源,出现了 并发式垃圾收集算法和并行垃圾收集算法【1 0 】。 j a v a 语言对多线程编程和同步提供了完善的支持【3 】,同步也是j a v a 程序中 开销较大的一部分。消除不必要的同步和减小同步的开销是很多研究的目标。主 要的技术有静态分析冗余的同步和采用轻锁与重锁的实现方式来减少同步开销 【4 】4 。j a v a 程序中通常运行很多线程,这在服务器应用上尤为明显,减少线程自 身的丌销也十分重要。 异常处理是j a v a 语言中一个很重要的部分,虚拟机规范规定必须提供精确 的异常处理机制。异常处理方便了软件开发者,减少了软件开发中处理程序运行 错误的代价。然而异常处理的运行时开销十分巨大,异常处理也增加了虚拟机开 发的复杂度,它是虚拟机的每个部分都要慎重考虑到的。 除了虚拟机,运行j a v a 程序还需要j a v a 类库和j a v a 本地库。前者类似于c 语言标准库,是用j a v a 编写的库文件,其核心部分是与j a v a 虚拟机绑定在一起 的。j a v a 字节码是种简单的栈式机器语言,不具备胂的能力,凡是和o s 相 关的操作j a v a 程序都是通过本地库完成的。j a v a 本地库就是遵循j n i ( j a v an a t i v e i n t e r f a c e ) 规范 1 4 】的c 函数,这些c 函数一一对应到相应的j a v a 方法,称为j a v a 本地方法。当j a v a 程序调用了本地方法时,虚拟机会调用对应的c 函数,参数 和结果都按照j n i 规范传递。 3 本文的工作 2 第一章引言 本文中,我们通过移植s u nj d k1 5 到龙芯2 号样机上,解决了龙芯上高效 运行j a v a 程序的问题,并做了性能分析和一些优化工作。具体工作包括以下几 个方面: ( 1 ) 研究j a v a 虚拟机相关的各种技术,为在龙芯上开发移植j a v a 虚拟机做技术 准备工作。 j a v a 虚拟机是一个相当庞大的软件,涉及到了很多计算机理论和技术,包括 j a v a 虚拟机规范、字节码解释器、j r r 编译器、垃圾收集器以及编译相关的技术, 在进行虚拟机开发移植之前。先要对这些有所研究。 ( 2 ) 分析各种流行的j a v a 虚拟机的结构和优缺点,选择最适合的虚拟机移植到龙 芯上。 研究k a f f e 、j i k e s r v m 和h o t s p o t 等流行的j a v a 虚拟机的结构并比较它们的 优缺点,从运行性能、兼容性、可维护、持续开发等角度选择将s u nj d k1 5 移 植到龙芯上做为龙芯上的j a v a 运行环境的解决方案。 ( 3 ) 研究h o t s p o tj a v a 虚拟机,移植其到龙芯2 号上。 s u nj d k1 5 十分庞大,首先将其结构和原理分析清楚并拆分开来分别移植。 最主要的工作在于h o t s p o tj a v a 虚拟机,主要包括解释器、c i & c 2j i t 编译 器、垃圾收集器与内存管理、运行时环境、对象模型、异常处理以及本地库 等。移植的工作包括一个m i p s 汇编器的开发,并在此基础上开发运行时环 境、异常处理机制、字节码解释器和j i t 编译器等。 ( 4 ) 分析h o t s p o t 在龙芯2 号样机上运行j a v a 程序的性能问题,并做优化工作。 在龙芯2 号上运行j a v a 程序相对于c 肥+ + 程序速度要慢些,这主要是由于我 们是从x 8 6 版本的h o t s p o t 上移植过来的,很多设计是为x 8 6 体系结构做的,而 龙芯2 号是r i s c 体系结构的c p u ,这导致了在龙芯上运行j a v a 程序跳转指令 过多和访存瓶颈的问题。针对这些问题我们修改了适合于x 8 6 的一些设计;另外 利用龙芯2 号的寄存器多的优势做了一些优化工作。 ( 5 ) 分析服务器版h o t s p o t 虚拟机的结构并将其移植到龙芯上 服务器版h o t s p o t 的主要区别在于采用了服务器版j i t 编译器,它具有更加 复杂的编译过程,利用了一些高级的编译技术,这使得它能够编译出更高质量的 代码。但是它的编译开销也很大因此,服务器版h o t s p o t 更适合于运行那些长 期运行的服务器应用。服务器版j i t 编译器还需要字节码解释器的支持。 通过本文的上述工作,我们已经能够在龙芯2 号处理器样机上比较高效地运 行j a v a 应用。 4 本文的组织 下面介绍本文的组织结构: 3 基于龙芯处理器的j a v a 运行环境的移植与优化 第二章介绍j a v a 虚拟机的相关技术,包括j a v a 虚拟机规范、字节码执行方 式优缺点的比较、j l t 中的各种关键技术和垃圾收集算法的介绍等。 第三章比较了鼬f f c 、j i k e sr v m 、h o t s p o t 等j a v a 虚拟机的优缺点,往龙芯 上移植的可行性分析等。 第四章介绍h o t s p o tj a v a 虚拟机的结构和关键技术,虚拟机运行的主要原 理,j a v a 程序在h o t s p o t 上运行的一些细节。然后介绍了我们移植h o t s p o t 到龙 芯2 号上的过程和完成的主要工作。 第五章介绍了我们移植过程中遇到和发现的一些问题和已做的一些优化工 作,并给出比较数据。 第六章分析h o t s p o t 虚拟机在龙芯2 号样机上的运行性能,并与x 8 6 作出比 较,为以后的优化提供指导。 4 第二章j a v a 虚拟机相关研究 第二章j a v a 虚拟机相关研究 本章介绍j a v a 虚拟机相关的理论与技术及国内外在这方面的主要研究方向 与成果,包括j a v a 虚拟机规范、字节码解释器、j i t 编译器与垃圾收集算法等。 1 j a v a 虚拟机规范 j a v a 语言是一种强类型的、安全的和动态的面向对象语言。j a v a 是完全基于 u n i c o d e 的,在j a v a 虚拟机中所有j a v a 程序相关的字符串都是u n i c o d e 字符串, 这是j a v a 跨平台的一个重要基础。j a v a 语言内置了自动内存管理机制和对多线 程编程、网络编程、同步以及异常处理的支持。j a v a 源代码被编译成为平台无关 的字节码由在特定平台上实现的j a v a 运行环境运行,j a v a 运行环境的核心部分 是一个j a v a 虚拟机,命令行工具通过调用它执行j a v a 程序,虚拟机执行j a v a 程 序和j a v a 库代码,其中可能会调用j a v a 本地库。图2 1 是j a v a 运行环境的示意 图。 图2 1j a v a 运行环境示意图 1 1j a v a 类型与对象 j a v a 类型包括基元类型和引用类型两种,基元类型即b o o l e a n ,b y t e 、c h a r 、 s h o r t 、i n t 、l o n g 、f l o a t 和d o u b l e ;规范定义了这些类型的大小,在所有平台上完 全一样,这避免了c 语言在不同平台上基元类型数据大小不一致的问题。引用 类型即类( c l a s s ) ,相应的数据称为对象。所有j a v a 对象都是在堆中的,只能通 过引用访问他们;概念上可以把引用当成指针,虽然它们有着本质的不同。因此, 基于龙芯处理器的j a v a 运行环境的移植与优化 如果在j a v a 中声明一个对象,实际上它只是个引用,必须明确新建一个对象并 赋值给它才完成了对象的定义。上文提到的引用准确地说应该称为强引用,j a v a 中还有三种引用类型,分别是弱引用、软引用和影子引用【2 】。所有对象在堆中 通过各种引用关系构成了一个网络,这个网络通过根集,即堆栈中的引用和全局 引用( 类引用域成员和线程对象中的引用数据) ,被j a v a 程序访问;这是垃圾收 集的基础。 如果不考虑接口( i n t e r f a c e ) ,引用类型之间的继承关系构成了一个倒树结构, 树的根是j a v a 1 a n g o b j e c t 类型。每个j a v a 类、方法等本身也用一个j a v a 对象来 描述,称为反射数据( r e f l e c t i o n d a t a ) ,如类对应于c l a s s 对象、方法对应于m e t h o d 对象,这给予了j a v a 极大的灵活性。 1 2j a v a 程序的组成 j a v a 程序由j a v a 类组成,j a v a 类包括方法成员、域成员和类( c l a s s ) 成员( 内 部类) ,它们都可以是实例成员或者静态成员( s t a t i c ) 。静态成员属于类,实例成 员属于对象,类似予c + + 的概念。每个j a v a 类可以有一个类初始化方法,它在 类被载入时调用,负责初始化类,这与c + + 不同。j a v a 类被组织成包( p a c k a g e ) 管理,这使得在p u b l i c p r i v a t e p r o t e c t e d 三种访问权限之外产生了第四种即 p a c k a g ep r i v a t e 2 ;j a v a 类的全限定名称就是在类名之前加上p a c k a g e 名,虚拟 机中使用全限定名称确定一个类。p a c k a g e 之间是完全平等的,如j a v a n i o 和 i a v a n i o c h a r s e t 之间并没有名字所表现出来的父子关系。每个j a v a 类包括内部类 都被编译成个c l a s s 文件,j a v a 程序就是由一个或多个c l a s s 文件组成的。 同c 程序一样,j a v a 程序也有一个m a i n 方法,不同的是这个m a i n 不是全 局的,而是个静态方法。每个j a v a 类都可以包括一个m a i n 方法,运行j a v a 程序时需要指定主类,虚拟机将会运行它的m a i n 方法。m a i n 方法通常会生成一 些对象并调用它们的方法,或者调用本类或其他类的静态方法。这些动作都涉及 到动态类载入机制,这是j a v a 程序动态性的根本所在叫a v a 类是在运行时载 入并链接的,这些类的c l a s s 文件可以来自任何地方,如网络、文件系统等,还 可以即时在内存中生成。在程序运行之前,只有m a i n 是确定的,所有其它都只 是符号链接,无法保证程序两次运行中的符号链接指向的是相同的目标。j a v a 程序这种完全动态的特征给j a v a 程序带来极大的灵活性和安全性的同时,也给 j a v a 虚拟机高效运行j a v a 程序带来了挑战,国内外有很多这方面的研究。 c l a s s 文件包括了j a v a 程序的所有代码和数据,它的格式是虚拟机规范最 重要的部分之一。下面是c l a s s 文件的简单描述: c l a s s f i l e u 4m a g i c ; 0 x c a f e b a b e ,用于标志c l a s s 文件格式 6 第二章j a v a 虚拟机相关研究 u 2m i n o rv e r s i o n ; c l a s s 文件格式的次版本号 u 2m a j o r 文件格式的主版本号_ v e r s i o n ; c l a s s u 2c o n s t a r r _ , p o o l _ c o u n t ; 常量池中项目个数 c p j n f oc o n s t a n t _ p o o l c o n s t a n t _ p o o l _ c o u n t - 1 】;常量池 u 2a c c e s sf l a g s ; c l a s s 文件所描述的j a v a 类的访问权限 u 2t h i sc l a s s ; 描述本类的数据在常量池中的索引 u 2s u p e r 描述父类的数据在常量池中的索引c l a s s ; n 2i n t e r f a c e s 本类直接实现的接口的数目c o u n t ; f l u 2i n t e r f a c e s i n t e r f a c e s _ c o u n t ;描述本类直接实现的接口 u 2f i e l d sc o u n t ; 本类或直接实现的接口中定义的域的个数 f i e l d _ i n f of i e l d s f i e l d s _ c o u n t ;描述域,包括类成员和实例成员 u 2m e t h o d s _ c o u n t ; 本类或直接实现接口中定义的方法个数 m e t h o d _ i n f om e t h o d s m e t h o d s _ c o u n t ; u 2a t t r i b u t e s _ c o u n t ; 属性表中项目个数 a t t r i b u t e _ i n f oa t t r i b u t e s a t t r i b u t e s _ c o u n t ; 本类的属性表 ) 这是一个相当简明的文件格式。c l a s s 文件是大尾端格式( b i ge n d i a n ) 的,这是 规范规定的。 1 3 动态类载入机制 当虚拟机运行中第一次遇到一个类( 或接口,下略) 时,该类就被类载入器 动态载入到虚拟机中,即解析成虚拟机可以方便使用的数据结构;这可能是新建 一个对象、执行一个强制转换操作、执行类的静态方法或读取类的静态域。类载 入机制是j a v a 动态性和安全性的基础。与已经存在的其他动态链接机制不同的 是,j a v a 的动态类载入机制提供了延迟载入、类型安全的链接、用户可定义的类 载入策略和多重名称空间等特性【3 ,1 5 1 。 程序可以定义自己的一个或多个类载入器,类载入器实际上也是个j a v a 对 象,它的类是c l a s s l o a d e r 。自定义载入器需要实现方法l o a d c l a s s ;( s t r i n g n a m e ) , 它载入指定名称的类,返回相应的c l a s s 对象。l o a d c l a s s 方法可以选择自己载入 类或者调用另外一个类载入器的方法,后者称为委托,实际定义类的那个载入器 被称为类的定义载入器,最先发起载入的被称为原始载入器【3 1 。定义载入器的 i o a d c l a s s 方法先取得类的数据,然后调用c l a s s l o a d e r d e f i n e c l a s s 定义类;必须 是c l a s s 文件格式的数据,它可以来自任何地方一文件、网络等。 不同类载入器载入的相同全限定名称的类具有不同的类型;一个类由其原始 载入器和全限定名称完全确定如此,类载入器实现了名称空间的功能。当前类 载入器为虚拟机正在执行的j a v a 方法所属类的类载入器;当执行过程中遇到一 个类时( i - 文提到的四种情况) ,虚拟机在当前类载入器中查找该类,如未找到, 7 基于尼芯处理器的j a v a 运行环境的移植与优化 则调用当静类载入器的l o a d c l a s s 方法载入它。这种机制既实现了完全的动态性 又确保了自定义载入器不会影响程序的安全性。 1 4 多线程与同步 j a v a 语言内置了对多线程和同步编程的支持。 虚拟机规范规定每个j a v a 对象都关联一个m o n i t o r 对象,使得可以在任何 j a v a 对象上执行l o c k 、u n l o c k 、w a i t 和s i g n a l 等操作。有两种基本的同步方法, 即直接使用j a v a 对象的同步方法或者使用同步方法,语句块( s y n c h o n i z e d ) 。实际 程序中真j 下被用于同步的j a v a 对象非常少,一种显而易见的优化方法是在对象 被用于同步时才为其创建m o n i t o r ;进一步地,由于出现竞争的情况非常少,一 些研究提出了轻锁和重锁的概念来减少同步操作的时空开销【4 】。另外一些研究 , 发现j a v a 程序中超过9 0 的同步是多余的【1 6 】,采用逃避分析等方法发现不需要 被同步访问的对象。 先区分下文中常提到的几个线程的概念。系统线程是指操作系统上的线程, 如l i n u x 下的p t h r e a d 。j a v a 线程是指j a v a 程序中的线程,每个j a v a 线程都有 个相应的t h r e a d 类型的j a v a 对象;虚拟机规范没有规定实现j a v a 线程的方式, 具体实现可以选择最合适的方法。虚拟机通常也是个多线程的程序,虚拟机线程 一般被实现为系统线程。 1 5 方法与字节码 方法是虚拟机执行j a v a 字节码的基本单位。方法分为本地方法和j a v a 方法。 本地方法实现在本地库中,用于执行j a v a 字节码无法完成的任务如i o 操作,它 遵循j n i 规范【1 4 】;j a v a 方法由j a v a 字节码组成。另外一种方法分类是静态方法、 虚方法和特殊方法( 构造函数等) ,两种分类方法是正交的。静态方法和特殊方 法在类载入的时候就可以确定并链接;j a v a 程序中更多的是虚方法,所有没有 s t a t i c 和f i n a l 关键字修饰的非构造方法都是虚方法。虚方法包括普通虚方法和接 口方法。虚函数是影响j a v a 程序运行性能的一个重要因素,它不仅需要运行时 的丌销还拒绝内联。很多研究力图减少虚函数的开销。 虚拟机要求j a v a 方法运行时有一个关联的j a v a 栈帧,j a v a 栈帧中包括方法 的局部变量区和表达式栈。表达式栈是字节码执行的基础。本地方法也有相应的 本地栈帧,虚拟机规范没有要求这两种栈帧必须使用同一个栈。实际上虚拟机根 本没有要求j a v a 栈帧必须存在于栈中,它可以是任意一块内存;也不要求连续 的j a v a 方法调用产生的j a v a 栈帧是连续的,局部变量区和表达式栈也没有必要 是连续的或有任何关系。虚拟机规范对表达式栈的状态做了严格的规定,它确保 8 第二章j a v a 虎拟机相关研究 从任何路径执行到一处代码的表达式栈具有相同的状态;这里说的状态包括表达 式栈深度和其中数据的类型。方法的返回值放在表达式栈顶,它必须是表达式栈 中的唯一数据。表达式栈和局部变量区由s l o t 组成,每个s l o t 是3 2 位大小,l o n g 和d o u b l e 数据占用两个s l o t ( 不要求对齐) ,虚拟机中使用s l o t 编号确定局部变 量。 j a v a 字节码执行过程中实际上就是局部变量和表达式栈之间数据的各种操 作,如i l o a d 指令将指定s l o t 的i n t 类型局部变量载入表达式栈顶,i a d d 将表达式 栈顶的两个缸n 类型数据弹出并将它们的和压入表达式栈顶。 1 6 异常处理机制 t h r o w a b l e 及其子孙类型的对象被称为异常对象。在j a v a 程序中可以通过 t h r o w 语句抛出异常或由虚拟机抛出异常( 如数组越界、强制转换失败等) 。一旦 异常被抛出。虚拟机将中止当前方法的执行并开始异常处理。j a v a 语言提供了 t r y 、c a t c h 、f i n a l l y 等语句来处理异常【2 】。c a t c h 和f i a n a l l y 语句块被称为异常处 理例程,每个竹语句块都至少有一个关联的异常处理例程;t r ) r 语句块中的代码 被异常处理例程控制,不同的例程有不同的控制距离即代码中的距离。c a t c h 语 句指定了它处理的异常的类型;t r y 语句执行中无论是否发生异常,它所关联的 f i n a l l y 语句块都会执行。f i n a l l y 语句块通常被用来释放资源。 异常发生后,虚拟机先将表达式栈清空,再将异常对象压入表达式栈中。然 后为其在当前方法中按照控制距离由近到远的方式寻找c a t c h 例程,在寻找过程 中所有控制异常发生处代码的f i n a l l y 例程总被执行。一旦找到c a t c h 例程,虚拟 机跳到那里执行异常处理例程,然后跳到t r y 语句块之后运行;否则,当前方法 执行异常结束,相应的j a v a 栈帧被清除,虚拟机继续到调用它的方法中寻找c a t c h 例程,这个过程称为u n w i n d 。 虚拟机规范要求实现精确的异常检查机制,即异常必须在发生的地方被立即 抛出并处理。这给j a v a 程序运行带来了很大开销并给j i t 编译器的开发带来了困 难。 1 7 动态类型检查 不同于c + + 语言,j a v a 语言要求强制类型转换和引用赋值必须执行动态类型 检查【2 】,这使得j a v a 成为强类型语言,提高了j a v a 程序的可靠性。在面向对象 语言中引用赋值十分频繁,其中绝大多数动态类型检查是多余的。j a v a 程序中通 常使用了庞大的类库,动态类型检查有很大的开销。在j a v a 出现之前的很多研 究基于对类型进行巧妙的编码来实现快速的动态类型检查;但是这些类型检查系 9 基于尼罄处理器的j a v a 运行环境的移植与优化 统无法运用在很大的类库上,而且很难动态扩展。【1 7 】通过为每个类型维护一个 其祖先类型的列表实现了一个高效的动态类型检查机制,很多虚拟机实现采用了 类似的方法。 2 字节码执行方式 字节码执行方式主要有解释执行、j l t 编译执行和混合执行三种。解释执行 每次读入一条字节码译码并解释执行它。j a v a 字节码是一种基于栈的机器语言, 几乎所有字节码指令都包含对表达式栈顶数掘的操作,因而大多数j a v a 字节码 执行都需要两次或更多次内存访问,这和现代基于寄存器运算的处理器特别是 r i s c 处理器形成鲜明对比。解释执行j a v a 程序时,大量的机器时间浪费在对表 达式栈的操作上。另外每解释执行完一条字节码就需要执行一次跳转以执行下一 条字节码指令,这个开销也很大。面向对象语言开发的程序中通常包含大量的小 方法,传统的静态编译中通常内联这些小方法以减少调用这些小方法的开销。 j a v a 是典型的面向对象语言,j a v a 程序含有大量的小方法甚至数目不少的空方法 ( 构造函数等) ,解释执行j a v a 程序花在小方法调用上的时间很多。由于上述及 其它种种原因,解释执行速度很慢,这是早期j a v a 倍受指责的一个最主要原因。 j r r ( j u s t i nt i m e ) 编译执行早在j a v a 出现之前就被应用在l i s p 、s m a l l t a l k 和 s e l f 等语言中。j i t 编译执行j a v a 程序通常以方法为单位,在j a v a 方法第一次被 调用时将其编译为本地代码,以后每次执行该方法时都是运行编译后的本地方 法。不同于静态编译,j i t 编译需要在生成代码质量和编译时间之间作出平衡, 无论偏向哪一者都可能造成虚拟机性能的损害。j i t 编译是一种典型的动态编译 技术,它也有一些静态编译不具备的优点。动态编译可以利用运行时p r o f i l e 信 息束进一步优化代码而不是仅仅根据静态分析的结果来优化。动态编译可以进行 代码重排来减少代码运行时的缺页次数和缓存未命中次数,减小程序的工作集。 动态编译可以动态地进行内联,它甚至可以内联虚方法,这是静态编译做不到的。 通常认为j l t 编译执行j a v a 字节码的速度是解释执行的1 5 倍左右【7 1 。 程序局部性原理认为决定程序运行性能的只是小部分代码,j i t 编译器对所 有j a v a 方法一视同仁地编译,这是不合适的。一些j a v a 方法被执行的次数很少 甚至仅一次( 如类初始化方法) ,编译这些方法得不偿失;不同方法执行次数有 很大差别,对它们采用同样的编译力度也是不合适的。由此,出现了解释器和 j i t 编译混合执行字节码以及自适应优化j i t 编译两种技术。混合执行方法根据 一定的启发因素( 如已被调用次数和是否有循环等) 决定是否编译一个j a v a 方 法;自适应优化编译则根据运行时p r o f i l e 信息决定是否采用更大力度的优化措 1 0 第二章j a v a 虚拟机相关研究 施重新编译一个方法,它甚至可以选择优化方法中经常运行的部分代码( 如循 环) 。 混合执行和自适应优化j t 编译都涉及到一种称为o s r ( o n s t a c k r e p l a c e m e n t ) 1 8 的技术。当虚拟机认为一个正在运行中的方法( 通常是正在执 行一个循环) 需要被编译或者优化编译时,o s r 就发生了。简单的说o s r 就是 在方法正在运行时将其从一种执行方式转换到另外一种执行方式上。 本节的剩余部分将简单介绍一下解释执行和j i t 编译执行的大致原理。 2 1 解释执行字节码 字节码有两种解释执行方式,一种是采用s w i t c h 语句实现,种称为线性解 释( t h r e a d i n gi n t e r p r e t e r ) ,见图2 2 示例。 lg e n e r a t e a n dd i s p a t c h i n t e r p r e t et h eb y t e c o d e i n c r e m e n tt h eb c i bg e tt h en e x tb y t e c o d ef r o mb c hg e tt h ee n t r yf o rb ei nd i s p a t c h _ t a b l e j u m pt ot h ee n t r y k a 疗b 字节p 解释器示意图 h o t s p o t 字节码解释器示意图 图2 2 两种解释器结构示意图 前者在代码中用s w i t c h 语句跳转到每个字节码的解释代码开始处运行,并循 环执行下一条字节码指令;即使编译器对s w i t c h 语句进行了优化,这种实现在寻 找字节码的解释代码时也带来了至少l g ( n ) 次比较和跳转操作,其中n 是字节码 指令的数目。这种解释方式一般使用c 和c + + 等高级语言实现,效率偏低。 线性解释使用字节码作为索引访问一个跳转表,跳转表中是相应字节码的解 释代码地址,每执行完一个字节码就取出下一个字节码的解释代码地址并跳转到 那里去。线性解释省去了寻找解释代码的比较和跳转开销;但是它执行下一条字 节码指令的跳转使用寄存器作为跳转目标,这会造成c p u 跳转目标猜测未命中 从而影响流水线的性能,这在r i s c 体系结构上表现得尤为明显。 u 基于龙芯处理器的j a v a 运行环境的移植与优化 解释器的一个优点是它的代码非常小,实现容易,适合嵌入式设备等资源有 限的环境。解释执行j a v a 字节码的指令缓存未命中通常也很少。 2 2j i t 编译执行 由于在运行时编译,j i t 编译通常只能采用时空开销较小的编译技术、实现 有限的优化。本节描述j l t 编译执行j a v a 方法的大致过程和涉及到的一些技术。 编译的第一步是对j a v a 方法进行流分析,得到基本块信息和异常信息。通常 这一步是生成一种和字节码非常接近甚至是一对一关系的中间表示( h i r ) ,方 法内联和代码( 基本块) 重排也在这一步完成。分 析的过程基本上是对字节码解释执行一次的过程。 经过这一步大多数对栈的操作都被消除,所有运算 直接使用寄存器,仅在寄存器不够使用时才将寄存 器的内容写入内存中,这称为s p i l l 。j i t 编译执行 通常不再需要表达式栈,它被s p i l l 区域取代;局部 变量区是必需的。不同的虚拟机实现可能直接从上 面得到的中间表示生成代码或者做一些优化生成 另外一级中间表示( l i r ) 。寄存器分配通常在这 一步进行。最常用的图着色( g r a p hc o l o r i n g ) 寄 存器分配算法 1 9 1 由于开销太大般不能使用,相 对快速、效果又相当不错的线性扫描寄存器分配算 法【2 0 恻被大量地使用。有的实现还在这一步做窥 孑l 优化、冗余计算消除等优化。 图2 3j i t 编译过程 最后产生代码,这一步要进行代码安装、处理重定位、为不同调用场景设置 跳转路径、产生异常处理信息等。由于第一步通常要求多次遍历字节码,它占用 整个编译过程中的时间往往最多。图2 3 是j a l a p e f i oj i t 编译过程的示意图。 j a v a 程序动态执行的特点给j i t 编译带来了一些困难。j i t 编译时,相关的 j a v a 类可能还没有被载入,此时无法生成高效的代码,常见的技术是生成代码在 第一次运行到那里时载入类,并且改写代码为高效的方式,这个过程称为p a t c h 。 j a v a 中存在大量的虚方法调用,实际运行时调用的通常总是同一版本。种优化 措施是假设调用的总是某个方法,并做快速的运行时检查,一旦发现运行的不是 假设的方法,就重新生成代码。这个技术也能用于内联虚方法。 第二章j a v a 虚拟机相关研究 在运行编译后的j a v a 方法中可能会由于异常、被调试等原因需要重新运行 在解释方式下。这个过程与o s r 相对应,称为d e o p t i m i z a t i o n 。需要处理被内联 的方法中发生d e o p t i m i z a t i o n 的特殊情况,此时需要为每个运行中的j a v a 方法恢 复解释栈帧。 j i t 编译器生成的本地代码需要调用c c + + 代码完成一些复杂的任务如复杂 数学运算( s i n ,o o $ 等) 、异常处理、方法调用等。因此j i t

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论