kvm文档翻译-第六章

说明

翻译KVM的文档,只是为了个人学习以做记录.如果有翻译不周到的地方,请指出,我会修正的.

为何翻译该文档

此KVM不是目前特别火的Kernel-based Virtual Machine(一个开源的系统虚拟化模块).而是一个JAVA 的虚拟机.是J2ME cldc 的一个实现.其源码的难度比hotspot简单多了.因此,想通过研读KVM,以加深对hotspot的理解

编译选项,宏

本节列出了vmcomon/h/main.h中定义的各种C预处理器标志、定义和宏。了解这些标志的含义有助于移植工作,因此请阅读下面的文档和vmcomon/h/main.h文件。

注意 – 不要更改vmcomon/h/main.h中提供的值,这些值最好在端口特定的machine_md.h文件中被重写。

另外请注意,在我们的引用实现中,这些标志中的许多通常都是从makefiles中重写的。

对于每个定义,我们给出一个简短的摘要及其默认定义。这些标志和宏也记录在vmcomon/h/main.h中。

普通的编译选项

以下定义控制在开始移植工作之前必须设置的与平台相关的常规编译器选项。不正确的设置通常会导致虚拟机故障。

#define COMPILER_SUPPORTS_LONG 1

如果编译器支持长(64位)整数,则启用此标志。

#define NEED_LONG_ALIGNMENT 0

指示KVM,主机操作系统和编译器的64位整数都需要8字节对齐。

#define NEED_DOUBLE_ALIGNMENT 0

指示KVM,主机操作系统和编译器,是否需要double8字节对齐。(只有在启用了浮点数支持时,此标志才有意义)

额外提示. 为了生成更好的代码,最好指定字节序.应该在平台相关的头文件中,将下面的其中一个设为1.

#define BIG_ENDIAN 0

#define LITTLE_ENDIAN 0

如果您将COMPILER_SUPPORTS_LONG 置为零,则无需将这些“endian”变量之一设置为“1”。(详见第9章。)

还要注意,如果编译器支持64位整数算术,并且已经设置了标志

#define COMPILER_SUPPORTS_LONG

您应该为long64和ulong64类型提供定义。如果编译器不支持64位整数(或者由于其他原因将标志设置为0),则会自动为您创建这两种类型的结构定义。(见第9章。)

系统配置选项

以下定义允许您控制要包含在平台中的组件和功能

#define IMPLEMENTS_FLOAT 1

打开或关闭kvm中的浮点支持。在那些符合CLDC规范版本1.1的实现中应为“1”,在那些符合CLDC规范版本1.0的实现中应为“0”。

#define PATH_SEPARATOR ‘:’

路径中使用的路径分隔符。只有在为基于命令行的系统使用默认类加载器时,此定义才有意义。(在vmcomon/h/loader.h中定义)

#define ROMIZING 1

打开或关闭类预链接/预加载(JavaDecompact)支持。如果启用此选项,KVM将直接在虚拟机中预链接所有系统类,从而大大加快应用程序的启动速度。详见第14章。

#define USE_JAM 0

在KVM内部是否启用 Java应用程序管理器(JAM)。

#define ASYNCHRONOUS_NATIVE_FUNCTIONS 0

指示KVM使用可选的异步本地函数。有关详细信息,请参阅第11.4节“异步本地方法”和第12章。

#define USE_KNI 1

这个选项是在kvm 1.0.4中引入的。启用后,系统将包含k本地接口(kni)所需的一些代码。如果你不打算使用Kni(你应该!),我们建议您关闭此选项,因为在关闭此选项的情况下,旧样式的本地函数将运行得稍快。有关kni的更多信息,请参阅kni规范。

Palm 平台特定的选项

以下定义允许您控制特定于Palm的系统配置选项。所有这些功能最初都是为PalmOS版本的KVM设计的,但它们也可能对其他平台有用。

注意 – Palm OS的CLDC实现不再可用。

#define USESTATIC 0

指示KVM使用特定于Palm的优化,其中某些不可变的运行时数据结构从“动态RAM”移动到“存储RAM”,以节省Java堆空间。此机制的假实现也可用于Windows和Solaris版本的KVM(用于调试)。

#define CHUNKY_HEAP 0

指示KVM使用一个优化,允许KVM在多个块或段中分配Java堆。这使得虚拟机可以在某些平台(如Palm OS)上分配更多堆空间。

#define RELOCATABLE_ROM 0

指示KVM使用优化,其中使用可重定位(可移动)表示来存储预链接的系统类。这允许将romized(javadecompacted)系统类存储在Palm OS等设备中。

Memory allocation settings

以下定义影响KVM分配的内存大小。

#define DEFAULTHEAPSIZE 256*1024

KVM在虚拟机启动时分配的Java堆大小。此值通常从makefiles中重写。请注意,从kvm 1.0.3开始,可以重写命令行中的堆大小值(在支持命令行操作的端口中)。堆大小值必须是可除以4的数字。数字必须在16K到64M之间。

#define INLINECACHESIZE 128

如果启用了EnableFastBytecodes选项,则在虚拟机启动时kvm保留的特殊内联缓存区域的大小。内联缓存机制通过使用Deutsch&Schiffman在20世纪80年代早期推广的技术来加速kvm中的方法查找。此处的大小表示为许多内联缓存项(每个项需要12-16字节,具体取决于目标平台)。

#define STACKCHUNKSIZE 128

KVM内的Java线程的执行堆栈在必要时自动增长和收缩。此值定义需要分配新堆栈块时新堆栈帧块的默认大小。减少默认堆栈块大小将使新Java线程的创建成本较低,但在运行需要大量堆栈空间的程序(即,具有大量嵌套方法调用的程序)时,将降低VM的执行速度

#define STRINGBUFFERSIZE 512

虚拟机在各种字符串操作中内部使用的静态分配区域的大小(字节)。

注意 – 作为一般原则,KVM在虚拟机启动时分配所需的所有内存。在运行时,所有内存都分配在预先分配的区域内。当然,如果虚拟机调用在Java堆外部执行动态内存分配的宿主系统特有的本地函数(如图形函数),情况可能会发生变化。

GC 选项

以下选项启用压缩垃圾收集。请注意,当前压缩不能在具有分段(非连续)内存体系结构的平台上使用。

#define ENABLE_HEAP_COMPACTION 1

如果将以下选项设置为非零值,则会导致每次分配都发生垃圾收集。这样更容易发现垃圾收集问题。由于此选项使虚拟机运行非常缓慢,因此应在生产版本中关闭此选项。

#define EXCESSIVE_GARBAGE_COLLECTION 0

类加载选项

一些KVM平台可能希望禁止将任何新类加载到任何系统包中。下面的宏定义包名称是否是这些受限制的包之一。默认情况下,该系统防止动态类加载到java.*和Javax.*

 #define IS_RESTRICTED_PACKAGE_NAME(name) \ 
 ((strncmp(name, "java/", 5) == 0) || \ 
  (strncmp(name, "javax/", 6) == 0))  

解释器执行选项 (since KVM 1.0)

以下宏允许您打开和关闭控制解释器执行的某些功能。生产版本的默认值如下所示。

#define ENABLEFASTBYTECODES 1

打开或关闭运行时字节码替换和方法内联缓存。此选项将虚拟机的性能提高约10-20%,但会将虚拟机的大小增加几千字节。请注意,字节码替换不能在字节码存储在非易失性内存(如ROM)中目标平台上执行

#define VERIFYCONSTANTPOOLINTEGRITY 1

指示虚拟机在运行时执行常量池查找时验证常量池项的类型。稍微降低运行时性能,但出于安全和安全原因,通常建议保持运行时性能。

其他定义和解释器宏:

#define BASETIMESLICE

此变量的值确定虚拟机执行线程切换、事件通知和其他定期需要的操作的基本频率(作为执行的字节码数)。较小的数目可以减少事件处理和线程切换延迟,但会导致解释器运行更慢。

#define DOUBLE_REMAINDER(x, y) fmod(x,y)

在interpret中定义的一种编译宏,用于查找两个浮点数的模。

#define SLEEP_UNTIL(wakeupTime)

此宏使虚拟机休眠,直到当前时间(由函数currentTime_md()的返回值指示)大于或等于唤醒时间。sleep_until的默认实现是一个繁忙的循环。出于节约电池的原因,大多数平台通常都应该提供更有效的实现。更多详情请参阅第12.4节“电池节电”。

解释器执行技术(在kvm 1.0.2之后)

自1.0.2版发布以来,kvm的解释器设计比kvm 1.0高出15-30%的性能,并且没有失去任何的ansi c c可移植性。实际的性能改进百分比取决于目标平台和用于编译KVM的C编译器的功能。性能改进是以下四种技术相互独立使用的结果:

  • 重新构造解释器代码,以便在解释器运行时将虚拟机寄存器放入本地C变量中。
  • 将不常用的Java字节码拆分为单独的解释器循环子程序。这使得C编译器可以更好地优化代码以获得更频繁使用的字节码。
  • 将Java线程重新调度的测试从解释器循环的顶部移动到分支字节码。这减少了用于控制线程切换的时间片计数器的开销。
  • 填充字节码空间,以便C编译器为解释器的主switch语句生成更好的代码。

这些技术不依赖于任何特定于编译器的特性,因此可以跨各种C编译器进行移植。下面将详细讨论每种技术和相应的宏。

将虚拟机寄存器复制到局部变量

在执行字节码时,经常访问kvm的虚拟机寄存器(ip、sp、lp、fp、cp)。在kvm 1.0中,所有这些虚拟机寄存器都定义为全局C变量。从kvm 1.0.2开始,这些寄存器仍然主要定义为全局变量,但是如果LOCALVMREGISTERS选项为on,则在解释器执行时,它们将被复制到本地变量。然后,一个好的C编译器将优化解释器循环,以便将这些局部变量放入机器寄存器中,从而大大加快执行速度

#define LOCALVMREGISTERS 1

打开或关闭虚拟机寄存器的本地化

#define IPISLOCAL 1
#define SPISLOCAL 1
#define LPISLOCAL 0
#define FPISLOCAL 0
#define CPISLOCAL 0

这些宏允许您具体控制解释器循环应在本地使用哪些虚拟机寄存器。添加这些宏是为了更好地控制寄存器分配,因为许多受资源约束的平台可能没有许多可用的物理硬件寄存器。

为特定平台优化选择这些选项需要仔细检查编译器生成的机器代码,并进行大量实验。默认情况下,IP(指令指针)和SP(堆栈指针)在本地分配,而LP(本地指针)、FP(帧指针)和CP(常量池指针)保留在全局变量中。

注意 – 如果您使用LOCALVMREGISTERS选项,并且希望对实现Java字节码的代码做进一步的更改,记住的最重要的一点是确保虚拟机寄存器的本地副本在调用期望它们的虚拟机中的函数之前被复制回它们的全局变量。在它们的全局变量中。如果不这样做,将导致隐藏的错误。虚拟机寄存器可以使用宏vmsave保存到全局变量中。使用宏vmrestore将它们还原回其局部变量。例如,返回的字节码可能需要调用monitorexit(),为此,必须按如下方式进行调用:

VMSAVE
result = monitorExit(...);
VMRESTORE

将不常见的字节码拆分为单独的子例程

KVM 1解释器在单个大switch语句中拥有所有Java字节码的代码。然而,大多数Java字节码很少执行。如果将使用频率更高、使用频率更低的字节码的代码放在单独的例程中,C编译器通常可以更好地优化结果较小的解释器循环。这也有助于编译器在使用LOCALVMREGISTERS选项时更容易找到虚拟机寄存器的硬件寄存器

#define SPLITINFREQUENTBYTECODES 1

打开此选项允许C编译器为频繁和不经常使用的字节码生成单独的解释器循环。

请注意,处理字节码的代码现在包含在名为bytecodes.c的文件中。所有字节码的代码都保存在这里,并通过使用许多内部宏定义(STANDARDBYTECODES, INFREQUENTSTANDARDBYTECODES, FLOATBYTECODES 和 FASTBYTECODES)选择性地编译。

bytecodes.c中的代码是从另一个名为execute.c的新文件执行的。如果启用了SPLITINFREQUENTBYTECODES选项,则文件bytecodes.c将包含在execute.c中两次:一次用于名为SlowInterpret()的例程,另一次用于例程Interpret()。上面提到的四个宏用于控制将适当的字节码扩展到正确的子例程中。

将线程重新调度测试移动到分支点

旧的kvm 1.0解释器测试了在执行每个字节码之前是否需要重新调度(切换线程)。通过改变测试的位置,解释器的性能提高了5%左右,因此测试只在每个分支、goto、call和return指令之后执行。

旧解释器中的线程调度发生在执行了一定数量的字节码时。默认情况下,这个数字是线程优先级的100倍。在新的解释器中,当执行了1000次的分支、调用或返回字节码时,默认情况下会重新安排线程

#define RESCHEDULEATBRANCH 1

启用此选项将更改线程切换机制,以便将线程切换测试移动到分支点。请注意,启用此选项会影响从kvm 1.0继承的baseTimeslice宏的值。当此选项关闭时,线程调度与kvm 1.0中的一样运行。

填充字节码空间

Java虚拟机规范定义了200个标准字节码,另外还保留了四个其他字节码供其他用途使用。然而,当字节码(switch)表的大小正好为256时,许多C编译器会生成更好的代码。

#define PADTABLE 0

打开此选项将填充解释器交换表,使指令数为256。这将增加虚拟机的大小,但允许解释器在某些平台上更快地运行

Java-level 调试选项

KVM 1.0.2版本引入了一种新的Java级调试器接口,该接口允许KVM插入第三方Java调试器环境和支持JDWP(Java调试线协议)协议的集成开发环境(IDE)。本节中的宏与Java级调试器选项相关。

注意 – 重要的是要注意,用于Java级调试和VM级调试的调试设备之间存在根本区别。

Java级调试工具与KVM执行的Java程序的调试有关。VM级调试工具用于在本地(C)代码级别调试KVM本身。

#define ENABLE_JAVA_DEBUGGER 0

包含大量的调试器支持代码,这些代码是将KVM插入第三方Java调试器或集成开发环境(如FordE或Borland JBuilder)所必需的。

有关Java级调试器工具和KDWP接口的更多信息在第16章“Java级调试支持(KDWP)”中提供。

VM-level 调试 和 追踪 选项

KVM提供了大量的调试和跟踪工具,可用于在本地(C)代码级别检查KVM本身的行为。这些设施在移植过程中非常有用。

所有VM级调试和跟踪选项都应在生产版本中关闭

Includ 和 执行

#define INCLUDEDEBUGCODE 0

包括大量调试和日志记录代码,这些代码在将虚拟机移植到新平台时非常有用。此选项应在生产版本中关闭。

#define ENABLEPROFILING 0

打开或关闭允许您监视虚拟机执行并获取执行统计信息的某些分析功能。打开此选项会大大降低虚拟机的执行速度。此选项应在生产版本中关闭。

追踪选项

在kvm 1.0中,所有跟踪选项都是编译标志,只能通过重新编译虚拟机来更改这些标志。在kvm 1.0.2中,所有这些跟踪选项都被更改为可从命令行控制的全局变量。这使得打开和关闭单个跟踪选项更加容易。只有在启用INCLUDEDEBUGCODE模式编译虚拟机时,这些全局变量(和命令行开关)才可用。

TABLE 6  –  Command line tracing options
Option
Description
-traceallocation
追踪内存分配
-tracedebugger
trace the debugging interface (since KVM 1.0.3)
-tracegc
追踪gc
-tracegcverbose
追踪gc,更多详情
-traceclassloading
追踪类加载
-traceclassloadingverbose
追踪类加载,更多详情
-traceverifier
追踪 class file的验证
-tracestackmaps
追踪 stack maps 的行为
-tracebytecodes
追踪 bytecode 的执行
-tracemethods
追踪 方法调用
-tracemethodsverbose
追踪 方法调用, 更多详情
-traceframes
追踪 stack frames
-tracestackchunks
追踪stack chunk 的分配
-traceexceptions
追踪 异常 处理
-traceevents
追踪事件系统的处理
-tracethreading
追踪多线程系统的处理
-tracemonitors
追踪monitor的行为
-tracenetworking
追踪网络访问
-traceall
同时激活上面的所有跟踪选项

如果目标平台不支持命令行操作,则可以通过在文件vmcomon/src/global.c中更改这些选项的默认值,或通过定义设置和重置这些选项的图形用户界面来直接控制这些选项。

此外,您可以通过修改以下选项来控制打印出的跟踪消息是否简洁或更详细

#define TERSE_MESSAGES 0 

kvm还包含一个堆栈跟踪打印功能,可以打开它来帮助更详细地调试异常和错误(代价是占用一些额外的内存)。默认情况下,当INCLUDEDEBUGCODE标志打开时,此模式自动打开。

#define PRINT_BACKTRACE 0 

异常处理宏

注意 – kvm使用的内部错误处理宏已在kvm 1.1中重新设计,以支持重新设计的类加载器。
解释器使用内部错误处理宏,如代码示例1所示。

如果有对宏THROW(error)的调用,在“正常代码”内的任何地方,VM都会立即跳转到错误处理代码。此宏的使用可以嵌套,无论是在词法上还是动态上。throw跳转到最内部的catch错误处理代码。(各种try、throw和catch宏在vmcomon/h/global.h中定义。)

CODE EXAMPLE 1 Error handling macros
TRY { 
   normal code 
} CATCH (error) { 
   error handling code 
} END_CATCH 
   always continue here 

默认情况下,使用setjmp和longjmp模拟此行为。但是,已经提供类似机制的平台(如palmos)应该使用本地机制。

kvm 1.1也有新的宏来控制虚拟机的关闭。这些宏在代码示例2中进行了说明。

CODE EXAMPLE 2 VM shutdown macros
VM_START { 
   normal VM code 
} VM_FINISH (value) { 
   code to execute before VM shuts down 
} VM_END_FINISH 

与其调用普通的c exit函数,从vm退出的正确方法是调用macro vm_exit(value)。调用此宏将使vm的控件立即传输到VM_FINISH(value)宏后面的代码。传递给此代码的值通常表示关闭时VM将返回的退出代码。

其他宏和选项

#define UNUSEDPARAMETER(var)

引用实现中的某些函数采用了它们不使用的参数。有些编译器会发出警告,而有些则不会。对于发出警告的编译器,它们在如何指示不使用变量是有意的以及不希望收到警告方面有所不同。这个宏应该做任何必要的事情来让编译器保持安静。

重写makefiles中的编译标志和其他选项

在使用gnumake构建kvm时,通常使用以下参数。

gnumake ROMIZING=false 

在禁用romizing的情况下构建kvm。也就是说,不要静态地将所有系统类链接到KVM可执行文件中。(默认设置是在启用romizing的情况下构建kvm。)

gnumake DEBUG=true 

使用Java级调试器和VM内部调试代码构建KVM

gnumake USE_JAM=true 

使用启用Java应用程序管理器(JAM)来构建KVM

gnumake GCC=true 

使用GNU C编译器而不是标准的Sun编译器(在Solaris上)

gcc=true是在Linux上开发时的默认选项,这是使用cygwin工具在Windows上编译的设置。

gnumake USE_KNI=false 

构建不带kni功能的kvm。(默认设置是在启用Kni的情况下构建kvm。)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值