用于进行静态初始化的方法和系统的利记博彩app

文档序号:6416531阅读:110来源:国知局

专利名称::用于进行静态初始化的方法和系统的利记博彩app
技术领域
:本发明一般涉及数据处理系统,特别涉及用于进行静态初始化的方法和系统。JavaTM描述用于产生和运行平台无关代码的编程语言和编程环境。这种平台无关代码在JavaTM虚拟机上运行,这是一种解释平台无关代码的抽象计算机JavaTM虚拟机在Lindholm和Yellin的文章“TheJavaVirtualMachineSpecification”,Addison-Wesley(1997),中详细说明了,该文在此引为参考。Java虚拟机不专门识别JavaTM编程语言或任何其它编程语言;相反,Java虚拟机只识别特定的文件格式,类文件格式。类文件包含构成平台无关代码的Java虚拟机指令(或字节代码)。作为运行Java程序的一部分,开发人员经过若干步骤,如图1所示。首先,开发人员编制计算机程序(步102)。一般地说,开发人员已经用高级语言例如Java编程语言开发了包含源码的计算机程序,并调用JavaTM编译程序对代码进行编译。Java编译程序是可从加利弗尼亚州MountainView市的SunMicrosystems公司得到的JavaTM软件开发包的一部分。Java编译程序输出一个或几个含有适合于在Java虚拟机上执行的字节代码的类文件。每个类文件含有一种Java编程语言,可以是一个类或一个接口。类文件格式在“TheJavaVirtualMachineSpecification”pp.83-137中详细说明了。虽然类文件格式是健壮的文件格式,但是其不能命令虚拟机有效地静态初始化一个数组,因而便提出了一个问题,详述如下。在编译程序之后,开发者把在步102输出的类文件通过使用预加载程序(步104)统一成一个文件,叫做.mclass文件。预加载程序也从SunMicrosystems公司得到,其用于链接类文件并进行预处理以便于类文件的执行。在统一类文件之后,开发者将.mclass文件加载在虚拟机中(步106)。在本步中,Java虚拟机在存储器中存储.mclass文件,并通过读出字节代码并对其进行处理和执行来解释包含在.mclass文件中的字节代码。直到字节代码的解释被完成,.mclass文件才存储在存储器中。由Java虚拟机识别的字节代码在“TheJavaVirtualMachineSpecification”pp.151-338中更清楚地说明了。如上所述,类文件格式不能命令虚拟机静态地初始化数组,为了解决这个问题,JavaTM编译程序产生一个特定的方法,&lt;clinit&gt;,用于进行类初始化,包括静态数组的初始化。静态数组初始化的一个例子如下代码表#1staticintsetup[]={1,2,3,4};在本例中,数组“setup”包括要被静态初始化为1,2,3,和4的4个整数。已知静态初始化,JavaTM编译程序便产生&lt;clinit&gt;方法,该方法在功能上按照下述的伪码进行静态初始化代码表#2temp=newint[4];temp=1;temp[1]=2;temp[2]=3;temp[3]=4;this.setup=temp;如上述代码表所示,仅仅描述&lt;clinit&gt;方法在功能上便需要许多语句。不过,更重要的是,由字节代码进行的&lt;clinit&gt;方法的实际处理需要更多的语句。这些字节代码控制产生所需的静态初始化的堆栈。堆栈是由在Java编程环境下的方法使用的存储器的一部分。对于由上述的示例的静态初始化的&lt;clinit&gt;方法进行的步骤以字节代码表示如下代码表#3Methodvoid&lt;clinit&gt;()0iconst_4//整数值4入栈1newarrayint//建立新整数数组并入栈3dup//复制栈顶4iconst_0//整数值0入栈5iconst_1//整数值1入栈6iastore//数组下标0处存17dup//复制栈顶8iconst_1//整数值1入栈9iconst_2//整数值2入栈10iastore//数组下标1处存211dup//复制栈顶12iconst_2//整数值2入栈13iconst_3//整数值3入栈14iastore//数组下标2处存315dup//复制栈顶16iconst_3//整数值3入栈17iconst_4//整数值4入栈18iastore//数组下标3处存419putstatic#3&lt;Fieldfoobar.setup[I&gt;//根据栈中新数组修改设定数组22return虽然使用&lt;clinit&gt;方法为JavaTM编译程序提供一种方式命令虚拟机初始化一个静态数组,但是用于初始化数组所需代码的数量是数组大小的许多倍,因而需要大量的存储器。因此,需要改进静态初始化方法。所公开的系统代表对常规的用于初始化静态数组的系统的一种改进,其中减少了由虚拟机为静态地初始化数组而执行的代码的数量。为实现这种减少,当统一类文件时,预加载程序识别所有的&lt;clinit&gt;方法,并模拟执行(“假装执行”)这些方法,以便确定由这些方法执行的静态初始化。然后,预加载程序产生一个表示由&lt;clinit&gt;方法进行的静态初始化的一个表达,并把该表达存储在.mclass文件中,用于代替&lt;clinit&gt;方法。这样,包含许多指令的&lt;clinit&gt;方法的代码被一个命令虚拟机进行静态初始化的表达所代替,因而节省大量存储器。虚拟机被修正,以便识别这一表达,并对数组进行合适的静态初始化。本发明的方法在处理部件上接收要被运行的代码,以便进行操作。然后该代码在存储器上被模拟执行,而不在处理部件上运行该代码,以便识别该操作,看该代码是否已被处理元件执行。此后,对处理元件产生一个指令,以便执行这种操作。本发明的一种数据处理系统包括辅助存储装置,存储器和处理器。辅助存储装置包括具有静态初始化数据结构和类文件的源码的程序,其中一个类文件含有静态初始化数据结构的&lt;clinit&gt;方法。存储器含有编译程序,用于对程序进行编译并产生类文件和用于统一类文件的预加载程序,用于模拟执行&lt;clinit&gt;方法,从而确定&lt;clinit&gt;方法进行的静态初始化,并产生用于执行静态初始化的指令。处理器运行编译程序和预加载程序。图1是当在JavaTM环境下开发一个程序时执行的步骤。图2是本发明的数据处理系统。图3是由图2说明的预加载程序执行的步骤流程图。本发明的系统和方法提供一种改进的系统,用于通过利用一个或几个指令代替代替&lt;clinit&gt;方法,在JavaTM编程环境下初始化静态数组,其中所述指令当被虚拟机读取时,除去使用数量少得多的存储器和少得多的时间之外,使虚拟机进行和利用&lt;clinit&gt;方法进行的相同的静态初始化。结果,这种系统和方法在静态初始化数组时,可以大大减少存储器的利用。本发明的系统和方法通过在预加载程序中进行某种处理而消除了对&lt;clinit&gt;方法的需要。尤其是,预加载程序接收类文件,用于统一并扫描它们,寻找&lt;clinit&gt;方法。当预加载程序找到&lt;clinit&gt;方法时,便相对于存储器模拟执行(“假装执行”)&lt;clinit&gt;方法,以便确定如果由Java虚拟机解释则&lt;clinit&gt;方法对于存储器应当具有的影响。即,预加载程序模拟执行&lt;clinit&gt;方法,以便识别假如由JavaTM虚拟机执行&lt;clinit&gt;方法进行静态初始化而得到的结果。在识别这一静态初始化之后,预加载程序产生一个或几个指令(或指示),以便进行和&lt;clinit&gt;方法相同的初始化,并向Java虚拟机输出这些指令,因而代替&lt;clinit&gt;方法。然后,在运行时间,由Java虚拟机读出这些指令,使Java虚拟机进行和使用&lt;clinit&gt;方法时相同的静态初始化。所述指令需要的存储空间比&lt;clinit&gt;方法少得多。例如,在上述代码表#3描述的字节代码被减少为下面在.mclass文件内包含的指令,其指示4个整数的数组具有初始值1,2,3,和4CONSTANT_ArrayT_INT41234示例的实施例的虚拟机识别这一表达,并把数组静态初始化为合适的值。结果,示例的实施例在初始化静态数组时比常规的系统占用的存储器少。图2说明构成本发明的数据处理系统200。数据处理系统200包括和因特网204相连的计算机系统202。计算机系统202包括存储器206,辅助存储器装置208,中央处理单元(CPU)210,输入装置212,和视频显示器214。存储器206进一步包括JavaTM编译程序218,JavaTM预加载程序220和JavaTM运行时系统221.JavaTM运行时系统211包括JavaTM虚拟机222。辅助存储器装置208包括具有源码的程序224,不同的类文件226,以及。mclass文件228.JavaTM编译程序218把程序224编译成一个或几个类文件226。然后,预加载程序220接收类文件226,并产生代表所有这些类文件的统一化的.mclass文件228。在统一之后,.mclass文件228可在虚拟机222上运行。本发明的处理由用于搜索&lt;clinit&gt;方法的预加载程序220进行,当找到时,则预加载程序(1)模拟&lt;clinit&gt;方法的执行,以便确定如果其由虚拟机222解释则其对存储器具有的影响,(2)产生静态初始化指令复现这些影响,以及(3)以.mclass文件输出这些指令来代替&lt;clinit&gt;方法,这样便节省大量的存储器。此外,本发明的处理由虚拟机222进行,因为其被修改,以便识别预加载程序的静态初始化指令。虽然本发明的示例的实施例以被存储在存储器206中进行说明,但是本领域技术人员应当理解,它也可以存储在其它的计算机可读的介质上,例如辅助存储装置如硬盘、软盘或CD-ROM;从因特网204接收的载波;或RAM或ROM的其它形式。此外,本领域的技术人员应当理解,计算机202可以具有附加的或不同的元件。图3说明由本发明的预加载程序220执行的用于完成静态数组的初始化的步骤的流程图。由预加载程序进行的第一步是读出类文件,以便获得&lt;clinit&gt;方法(步302)。在获得&lt;clinit&gt;方法之后,预加载程序分配在模拟执行期间使用的各个变量(步304)。当模拟执行时,如下所述,预加载程序由虚拟机模拟包含在&lt;clinit&gt;方法中的字节代码的执行。这些字节代码控制和&lt;clinit&gt;方法相关的各种数据结构,例如常量存储库,堆栈,或局部变量(或寄存器)。常量存储库是一种可变长度结构的表,代表各种串常量、类名和其它属于类文件内的常量。堆栈是存储器的一部分,用于在方法的执行期间存储操作数。因而,堆栈尺寸是在执行该方法的任一时刻由操作数占据的空间的最大的数量。局部变量是由这种方法使用的变量。当分配变量时,预加载程序获得&lt;clinit&gt;方法的常量存储库的指针,为堆栈分配一个合适的尺寸,并这样分配一个数组,使得数组的每个项相应于每个局部变量。如下所述,则模拟执行根据这些变量操作。在分配变量之后,预加载程序读出来自&lt;clinit&gt;方法的字节代码(步306)。接着,预加载程序确定其是否识别该字节代码(步308)。在这一步,预加载程序识别所有字节代码的子集,该子集只含有一般用于进行数组的静态初始化的那些字节代码。下面是由一个示例的实施例的预加载程序识别的字节代码的表代码表#4acons_nulliastoreiconst_mllastoreiconst_0fastoreiconst_1dastoreiconst_2aastoreiconst_3bastoreiconst_4lastoreiconst_5sastorelconst_0duplconst_1newarrayfconst_0anewarrayfconst_1returnfconst_2ldcdconst_0ldc_wdconst_1ldc2_wbipushputstaticsipush任何和上述表中的字节代码不同的字节代码不被识别。除去上进字节代码之外其它字节代码的存在表明,&lt;clinit&gt;方法执行附加于静态初始化数组的功能。在这种情况下,&lt;clinit&gt;方法不可能被优化。如果字节代码不被识别,则预加载程序认为其对于优化(或模拟执行)是不合适的,并且处理继续到步316。然而,如果预加载程序识别字节代码,预加载程序就进行由字节代码表示的操作(步310)。在这一步,预加载程序根据在步304分配的变量模拟执行字节代码,结果,一个值可以从堆栈中弹出,可以更新局部变量,或从常量存储库中检索一个值。此外预加载程序可以遇见一个“putstatic”字节代码,其表示以特定方式要被初始化的特定静态变量(例如数组)。如果预加载程序接收这个字节代码,便将请求初始化的表示存储在一个散列表中供以后使用。例如,在散列表中的一个项如下Setup:=Array(1,2,3,4)在完成由字节代码表示的操作之后,预加载程序确定是否在&lt;clinit&gt;方法中具有更多的字节代码(步314)。如果有,处理返回步306。然而,如果没有更多的字节代码,预加载程序便在.mclass文件中存储命令,以便列数组进行静态初始化(步318)。在这一步,预加载程序在.mclass文件中存储常量存储库项如下标记类型尺寸值CONSTANT-ArrayT-INT41234这个在常量存储库中的项表示,一个特定的数组具有初始值为1,2,3,和4的4个整数。在运行时,当虚拟机初始化类.mclass文件时,它将遇到对于这常量存储库的一个引用,并产生合适的数组。结果,在&lt;clinit&gt;方法中包含的许多命令被减少为这一个表达,大大节省了存储器的数量和时间。下面的伪码描述示例的实施例的预加载程序的采样处理。预加载程序接收限定&lt;clinit&gt;方法的方法信息数据结构作为参数,这在“JavaTMVirtualMachineSpecification”pp.104-106中描述了。应当注意,所述的处理只是一个例子,例如,只有少数的字节代码被描述为被预加载程序处理的。不过,本领域的技术人员应当理解,在代码表#4中的所有字节代码都可以利用示例的实施例进行处理。代码表#5<prelisting-type="program-listing"><![CDATA[voidemulateByteCodes(Method_infomb)intnumberRegisters=mb.max_locals();//局部变量数intstackSize=mb.max_stack();//堆栈尺寸bytebyteCode[]=mb.code();//获得字节代码ConstantPoolconstantPool=mb.constantPool();//获得常量库Objectstack[]=newObject[stackSize];//为假装执行建立堆栈Objectregisters[]=newObject[numberRegisters];//为假装执行建立局部变量/*以空堆栈开始*/intstackTop=-1;//仅在有效单元之下/*静态目标图*/Hashtablechanges=newHashtable();try{booleansuccess;execution_loop:for(intcodeOffset=O,newCodeOffset;;codeOffset=newCodeOffset){intopcode=byteCode[codeOffset]&amp;OxFF;//0..255nextCodeOffset=codeOffset+1;//最普通值switch(opcode){caseopc_iconst_m1://-1入栈stack[++stackTop]=newInteger(-1);break;caseopc_bipush:nextCodeOffset=codeOffset+2;stack[++stackTop]=newInteger(byteCode[codeOffset+1]);break;castopc_lload_3://加载整数3的内容stack[++stackTop]=(Long)register[3];stack[++stackTop]=null;//长期使用栈中二字break;castopc_fsub:{//从下项减去栈顶floatb=stack[stackTop--].floatValue();floata=stack[stackTop].floatValue();stack[stackTop]=newFloat(a-b);break;}caseopc_ldc:nextCodeOffset=codeOffset+2;stack[++stackTop]=constantPool.getItem(byteCode(codeOffset+1));break;casesastore:{//将内容存入“short”数组shortvalue=(short)(stack[StackTop--].intValue());intindex=stack[StackTop--].intValue();short[]array=(short[])stack[StackTop--];array[index]=value;break;}caseopc_putstatic:{nextCodeOffset=codeOffset+3;intindex=((byteCode[codeOffset+1])&amp;OxFF<<8)+(byteCode[codeOffset+2]&amp;OxFF);Fieldf=constantPool.getItem(byteCode[codeOffset+1]);if(f.getClass()!=mb.getClass()){//只能修改自己类中的静量thrownewRuntimeException();}Typet=f.getType();if(t.isLong()||t.isDouble())++stackTop;Objetvalue=stack[++stackTop]Changes.put(f,value);//在数列表中加入表项break;caseopc_return:success=true;breakexecution_loop;default://未能理解的某些字节代码success=false;breakexecution_loop;}}}catch(RuntimeException){//任何运行时意外指示故障success=false;}if(success){<如“changes”数列表指示地修改.class文件><从类中去除该<clinit>方法>}else{<某些内容不可理解><不替换该方法>}}]]></pre>如上所述,Java虚拟机222,除去进行如下的修正之外,是一种标准的Java虚拟机,如同在“JavaVirtualMachineSpecification”中所定义的。常规的虚拟机识别各种常量存储库项,例如CONSTANT_Integer,CONSTANT_String,和CONSTANT_Long。这些类型的常量存储库项存储各种变量信息,包括初始值。然而,示例的虚拟机还识别常量存储库中的CONSTANT_Array项。在类文件格式中的CONSTANT_Array常量存储库项的格式如下代码表#6CONSTANT_Array_info{ultag;/*字面值CONSTANT_Array*/ultype;/*如下所示*/u4length;/*数元素个数*/unobjects[length];/*实际值*//*仅在type=T_CLASS时包括以下字段*/u2type2;/*常量库中CONSTANT_Class的下标*/}ul类型字段是下表所列的值之一字段uxobjects[length]是一个数值数组,提供数组的元素。数组中元素个数由常量库表项的长度字段给定。这些值的每个的实际大小如下除去T_CLASS之外,对于以上的所有类型,所示的字节是被存储在数组元素中的实际值。不过,每个u2本身是一个常量存储库项的下标。所指的常量存储库项本身必须是CONSTANT_Array,CONSTANT_Object,或者是特殊的常量存储库项O,表示一个NULL值。例如,为了表示以下的数组int[]={10,20,30,40};常量存储库项如下标记类型大小初值CONSTANT_ArrayTTNT410203040另一个例子表示下面的组newFoo[3]/*全部被初始化为NULL*/常量存储库项如下标记类型大小初值类CONSTANT_ArrayT_CLASS3OOOxx其中“xx”是常量存储库中的下标,表示常量存储库中的类FOO。如下的二维数组newbyte[][]={{1,2,3,4},{5,6,7,8}};通过使两个常量存储库项对子数组编码,并使两个附加项表示子数组之间的相关性而被编码。这编码相应于作为目标类型的数组和作为多个数组中的一个数组的多维数组的JavaTM概念。上述的二维数组的常量存储库项如下Entry1:CONSTANT_ArrayT_BYTE41234Entry2:CONSTANT_ArrayT_BYTE45678Entry3:CONSTANT_Class具有名字“[[B”并且标记类型大小初值类Entry4:CONSTANT_ArrayT_CLASS2Entry1Entry2Entry3其中每个Entry1,Entry2,和Entry3是相应于常量存储库项的下标的两字节编码。虽然根据最佳实施例说明了本发明的系统和方法,但是,本领域的技术人员应当理解,不脱离所附权利要求限定的本发明的范围和实质可以作出各种改变和改型。权利要求1一种数据处理系统中用于静态初始化数组的方法,包括以下步骤利用静态值编译包含该数组的源码,从而利用含有字节代码的clinit方法产生一个类文件,以便把数组静态初始化为静态值;在预加载程序中接收类文件;对于存储器模拟执行clinit方法的字节代码,以便由预加载程序识别数组的静态初始化;在输出文件中存储需要静态初始化数组的指令;以及由虚拟机解释指令,从而进行数组的静态初始化。2如权利要求1所述的方法,其中存储步骤包括以下步骤在常量存储库中存储常量存储库项。3如权利要求1所述的方法,其中模拟执行步骤包括以下步骤分配堆栈;从clinit方法中读出控制堆栈的字节代码;以及对分配的堆栈执行堆栈控制。4如权利要求1所述的方法,其中模拟执行步骤包括以下步骤分配变量;从clinit方法中读出控制clinit方法的局部变量的字节代码;以及根据分配的变量进行局部变量的控制。5如权利要求1所述的方法,其中所述模拟执行步骤包括以下步骤获得clinit方法的常量存储库的一个基准;从clinit方法中读出控制常量存储库的字节代码;以及进行常量存储库的控制。6一种用于数据处理系统中的方法,包括以下步骤接收要在处理元件上运行的代码,以便进行操作;模拟执行不在处理元件上运行的代码,以便识别所述的代码是否曾被处理元件运行过的操作;以及产生使所述处理元件进行所述操作的指令。7如权利要求6所述的方法,其中所述的操作初始化一种数据结构,并且其中模拟执行步骤包括以下步骤模拟执行所述的码,以便识别数据结构的初始化。8如权利要求6所述的方法,其中所述操作静态初始化一个数组,并且其中模拟执行步骤包括以下步骤模拟执行所述的代码,以便识别数组的静态初始化。9如权利要求6所述的方法,还包括以下步骤在处理元件上运行产生的指令,以便完成所述操作。10如权利要求6所述的方法,还包括以下步骤由虚拟机解释产生的指令,以便进行操作。11如权利要求6所述的方法,其中所述的操作对存储器有影响,并且其中模拟执行步骤包括以下步骤模拟执行所述代码,以便识别对存储器的影响。12一种数据处理系统包括存储装置,其包括具有静态初始化一种数据结构的源码的程序;以及类文件,其中一种类文件含有静态初始化所述数据结构的clinit方法;存储器,其包括用于编译所述程序并产生类文件的编译程序;以及用于统一所述类文件的预加载程序,用于模拟执行clinit方法,以便确定clinit方法进行的静态初始化,并用于产生进行静态初始化的指令;以及用于运行所述编译程序和预加载程序的处理器。13如权利要求12所述的数据处理系统,其中预加载程序包括一种用于产生含有被产生的指令的输出文件的机制。14如权利要求13所述的数据处理系统,其中存储器还包括虚拟机,用于解释产生的指令,以便进行静态初始化。15如权利要求12所述的数据处理系统,其中所述的数据结构是数组。16如权利要求12所述的数据处理系统,其中clinit方法具有静态初始化所述数据结构的字节代码。17如权利要求12所述的数据处理系统,其中所述产生的指令包括在常量存储库中的一个项。18一种计算机可读的介质,其含有用于控制数据处理系统而实现一种包括以下步骤的方法的指令接收要在处理元件上运行的代码,以便进行操作;模拟执行该代码而不在处理元件上运行该代码,以便识别所述的代码是否曾被处理元件运行过的操作;以及产生使所述处理元件进行所述操作的指令。19如权利要求18所述的计算机可读介质,其中所述的操作初始化一种数据结构,并且其中模拟执行步骤包括以下步骤模拟执行所述的代码,以便识别数据结构的初始化。20如权利要求18所述的计算机可读介质,其中所述操作静态初始化一个数组,并且其中模拟执行步骤包括以下步骤模拟执行所述的代码,以便识别数组的静态初始化。21如权利要求18所述的计算机可读介质,所执行的方法还包括以下步骤在处理元件上运行产生的指令,以便完成所述操作。22如权利要求18所述的计算机可读介质,所执行的方法还包括以下步骤由虚拟机解释产生的指令,以便进行操作。23如权利要求18所述的计算机可读介质,其中所述的操作对存储器有影响,并且其中模拟执行步骤包括以下步骤模拟执行所述代码,以便识别对存储器的影响。全文摘要所公开的系统代表一种对常规的用于初始化静态数组的系统的改进,其中减少了由虚拟机静态初始化数组而执行的代码的数量。为实现这种减少,当统一类文件时,预加载程序识别所有的<clinit>方法并模拟执行这些方法,以便确定由其进行的静态初始化。然后,预加载程序产生一个表达,其表示由<clinit>方法进行的静态初始化,并把该表达存储在.mclass文件中,以便代替<clinit>方法。例如,含有许多指令的<clinit>方法的代码被一个命令虚拟机进行静态初始化的表达代替,从而节省大量的存储器。虚拟机被修改,以便识别这个表达,并对数组进行正确的初始化。文档编号G06F9/445GK1238500SQ9910773公开日1999年12月15日申请日期1999年4月7日优先权日1998年4月7日发明者弗兰克·耶林,理查德·D·特克申请人:太阳微系统公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1