程序对象的串行化和解串行的版本适应的制作方法

文档序号:6346084阅读:189来源:国知局
专利名称:程序对象的串行化和解串行的版本适应的制作方法
技术领域
本发明一般涉及计算机程序,特别涉及在处理面向对象的程序设计中处理程序对象的技术。
在由面向对象的程序设计实现的应用程序中,应用程序的部件可由名为程序对象的程序设计结构体现。一个程序对象基本上可代表任何真实的或虚构的,有形的或无形的物体。比如,在一个工资管理系统中,一个对象可能被用于代表某一雇员或在一指定雇用期间雇员的工资。在一个飞机降落控制系统中,一个程序对象可能被用来代表单个飞机或一个特别的跑道。在同一个系统中,一个代表整个机场的程序对象可以代表控制塔同时也可包括或嵌入代表这个机场所有跑道的程序对象。
程序对象通常不能在超出创造它们的程序的执行周期后继续存在。代表对象的信息通常存在于易失性存储器如RAM的某些结构中还有存取和使用这些信息的属性通常只在创造这个程序对象的程序执行时存在。
已知的技巧允许一个执行着的程序去生成在一个可被记录和发送的形式中代表程序对象的信息,这就使一个程序在另一时间或地点读这个信息和再造这个程序对象成为可能。Java编程语言中程序对象的合适技巧在由加利福尼亚Palo Alto的Sun Microsystems公司出版的“对象串行化说明”中公开。这个说明可在因特网中由URLhttp//java.sun.com/products/jdk/1.1/docs/guide/serialization/spec/确认的“jdk-specification目录”中取得,在此作为参考。在此jdk-specification目录下,这个标准的内容目录由“serialTOC.doc.html”确认和还有一个系统结构的讨论由“serial-arch.doc.html”确认。其他信息可从Web Publishing Inc.出版的Jave World中获取。这些文章可从因特网上的分目录“javaworld directory”URL http//javaworld.com/javaworld/中取得。在javaworld的基本目录中两个相关文章的分目录和名字是jw-01-1998/jw-01-beans_p.html和jw-02-1998/jw-02-beans_p.html,在此作为参考。术语“对象串行化”是指产生代表程序对象的信息的串行流的过程,术语“对象解串行”指的是解读信息串行流和再造程序对象的过程。
对象的串行化和解串行可用来优化一个或多个应用程序所必须的处理过程。例如,应用程序的处理过程可被分成段,要完成那些段的必要的处理过程可通过两个或多个计算机系统来实现。一个计算机系统可执行一个应用程序的初始段,在这个段结束时,串行化一个或多个程序对象以捕获串行信息流中的处理状态。第二个计算机系统能通过再造代表串行信息流的程序对象继续应用程序的处理过程,由此还原在初始段结束时存在于第一个计算机系统中的处理状态,然后通过执行一个后继段继续这个处理过程。换言之,串行化的信息提供给多个计算机系统以解串行地执行相同段的处理过程。
令人失望的是,已知技术中用来串行化和解串行的程序对象把重要的限制强加于执行应用程序的程序改变上。应用程序纠正错误或添加新特性的改变可能需要程序对象中一个或多个定义了的结构的同步改变。程序对象定义的每一个改变都被当成是引入这个程序对象的一个新的“版本”。更确切的说,这种改变引入了一个定义程序对象结构的“类”的新版本。一个程序对象是定义其类结构的一个情况。
一个改变是可以向前兼容,即当使用一个类的后期版本的程序能成功的从使用这个类早期版本的程序中产生的串行信息中解串行那个类。一个改变是可以后向兼容的,即当使用一个类的早期版本的程序能成功的从使用这个类后期版本的程序中产生的串行信息中解串行那个类。兼容的改变是向前兼容和向后兼容两者。不兼容的改变缺少向前、后向兼容其一或两者。如果一个必要的改变是不兼容的,那个改变是不能被引进到任何计算机系统的,除非参与分布式网络的所有计算机已被改为使用相同的类版本。关于Java编程语言中影响程序对象的兼容和不兼容改变的其他信息,可从上文提到的jdk-specification目录中的“version.doc.html”文中,和上文提到的javaworld directory中的文章jw-03-1998/jw-03-beans_p.html中取得,两者在此作为参考。
因为类的改变一般而言是不兼容的,许多程序对象串行化的已知技巧自动生成当程序对象被串行化时使用的类版本的标识。这类技巧的实例在我们以上提到的网页中都有论及。此网页的分目录和名字是jw-03-1998/jw-03-beans_p.html,在此作为参考。这允许了一个程序相对于与用来定义对象新实例的类的现行版本而检测被串行化的程序对象的版本。如果版本不同,则生成一个错误或某种形式的程序例外以警告应用程序有潜在的不可兼容性。
如果一个被认为是可兼容的改变,已知技巧允许类设计师通过强迫串行化过程来覆盖自动版本标识功能以生成为早期类版本生成的新类版本相同的版本标识。这个技术使使用不同的但兼容的类版本来共享代表类的被串行化的程序对象的串行化的信息成为可能。遗憾的是,已知技巧中没有能允许使用不同的和不兼容的版本的程序共享被串行化了的信息。
本发明的目的是通过允许程序共享作为类不可兼容版本的实例的程序对象串行化的标识,为程序对象提供串行化和解串行。
根据本发明的一个方面,一种方法通过获取程序对象的版本标识以串行化作为对象类的实例的程序对象,并生成被确定为对象类和版本标识的函数的传递程序对象表示的串行化信息。
根据本发明的另一方面,一种方法解串行传递作为对象类的实例的程序对象的表示的已串行化信息,它是通过从串行化信息中获得对象类和程序对象的版本标识并为对象的一个或单个属性从串行化信息建立值,其中一个或多个属性的值作为对象类和版本标识的函数而建立。
本发明的这些方面可用能够应用这些方法的装置实现。它们也可通过一个由例如可执行程序指令的计算机系统的设备由从可读的媒介输送的程序的指令来实现。
根据本发明的另一方面,一个由装置可读的媒介传送串行化信息,该信息表示一个或多个程序对象,程序对象是对象类的实例,程序对象包含由串行化信息表示的多个程序对象的标识,对象类名称的标识,和对于每个有串行化信息表示的程序对象,各个程序对象的版本标识和各个程序对象的一个或多个属性的各个值。
根据本发明的进一步的方面,一个由装置可读的媒介传送一个或多个为装置所执行的程序指令以实现串行化或解串行一个作为程序类的实例的程序对象的方法。一个或多个程序指令包括一个含有取得各自的程序对象的版本标识的方法的对象类的定义,和一个含有用来识别将被串行化或解串行的各自的程序对象的一个或多个属性的方法的对象-描述符类的定义。
本发明的不同功能和它的优选实施方案要通过参考下面的附图讨论才能充分理解。下面的讨论内容和图示只能用做示例而不能理解为是代表本发明的范围。


图1是一个可用来执行本发明不同方面的计算机系统的框图。
图2是一个由例如类似网络的通信设施互连的多个计算机系统的框图。
图3所示的是按照程序对象版本表示程序对象来生成串行信息的基本过程。
图4所示的是图3所示的基本过程的特殊实现。
图5所示的是按照程序对象的版本从串行信息中创建一个程序对象的过程。
图6所示的是图5所示的个别执行的基本过程。
图7所示的是一个可用来生成代表一个或多个程序对象的串行信息的一个过程的结构。
图8所示的是代表一个或多个程序对象的用来读和处理串行信息的一个处理过程的结构。
图9所示的是可被用来决定是否一个程序对象类是从一个或多个被认为是可串行的基本类派生的过程。
图10是一个按照本发明的串行化过程产生的串行信息流的内容的示意图。
图11所示的是根据本发明的一个实施例派生程序对象类的层次和相关的对象-描述符类的层次之间的关系。
A.概述1.执行本发明可通过各种方式实现,包括在个人电脑的软件。图1是可用来实现本发明不同方面的计算机系统10的框图。CPU12提供计算资源。输入控制13代表如键盘或鼠标的输入装置14的接口。RAM19是系统随机存取存储器(RAM)。存储控制15代表包括如磁带或磁盘,或光纪录媒介的存储装置16的接口。存储媒介可用来纪录操作系统,实用程序和应用程序的程序指令,也可包括执行本发明的各个方面的程序实施例。显示控制器17提供显示装置18的接口。通信控制21代表连接通信设施20的通信信道21的接口。通信设施20可代表任何设施例如网络,交换机,或允许与其它装置通信的计算机系统10的点对点通信路线。
在所示实现中,所有主要系统部件连接至总线11,可能是代表不止一个的物理总线。例如,一些个人电脑只有一个与所谓的ISA或其他变异的ISA兼容的总线。别的计算机有附加本地局部总线标准PCI兼容的高带宽总线。在本发明的应用中不要求总线结构。
应用本发明的不同方面时必要的属性可通过用多种方法实现的部件来实现,这包括分立逻辑元件,一个或多个ASCI和/或程控处理器。对本发明而言这些元件实现的方式并不重要。例如,实现本发明的必要操作可通过存在存储设置16中的程序指令在如计算机系统10的计算机系统中执行,并复制到RAM19由CPU12执行。
这种软件可由多种机器可读的媒介传递,包括磁带,磁盘,光碟,遍及从超声波频率到紫外线频率光谱的基带或调制通信路线。不同方面也可由装在计算机系统10中的不同元件执行,通过例如ASIC,通用集成电路,和配置在不同形式的ROM或RAM及其他技术中的程控微处理机进行。
2.串行信息的分布使用图2是一个由类似因特网的网络的通信设施20互连的多个计算机系统的框图。在所示的实施例中,计算机系统8,9,10作为在网络中与一个或多个服务器5,6交互的客户。该实施例只当作计算机系统互连的示例。该实施例中的特定特征与本发明无关。
一个如计算机系统10的装置可通过写串行信息到含有存储设置16的存储媒介或由通信设施20提供的通信路线上,或在此读串行信息,从而实现本发明多方面的操作。这个串行信息用来表示一个或多个程序对象,允许在某一特定时间和地点建立的程序对象在另一时间和/或地点重新建立。该功能使应用程序处理过程在时间和/或地点上分布成为可能。
于此所示,术语“串行信息”指的是用串行的方式记录或传递的信息,但是,这种信息基本上可用任何形式记录或输送。比如说,“串行信息”可能由信息化元素如字节,解串行记录或输送的二进制位,组成。
在图2所示的实现中,例如,本发明可通过允许计算机系统10,利用连接在通信设施20上其他的计算机系统资源,来分布实施个别应用程序的处理过程。这可通过让计算机系统10产生代表一个或多个程序对象的串行信息,并发送那个串行信息到另一个计算机系统如客户8来实现。服务器5和/或6能用来实现计算机系统之间串行信息的传递。一个在客户8上执行的应用程序能从通信设施20接收的串行信息建立一个或多个存在于计算机系统10的程序对象的对应程序对象,并完成适合客户8的有效资源的任务。这些任务的完成会修改一个或多个被传送的由客户8产生的串行信息的程序对象。这个串行信息可传到另一个计算机系统中做后继处理。
同样的,某一计算机系统通过生成代表一个或多个程序对象的串行信息,并把此串行信息写到存储装置16上,在时间上分布处理。在此之后,一个应用程序用从存储装置16读到的串行信息建立对应程序对象。
该机制运做正常直到有影响类结构的改变或程序对象定义被引进到一个或多个应用程序中。类结构的改变能够为这些应用程序改正错误或添加新功能。在个别计算机系统中执行的应用程序产生这种改变的能力,常被为保留在多个计算机系统中执行的应用程序之间程序对象的兼容性该要求所阻碍。兼容性是不可缺少的,这样那些被分布的应用程序才能共享代表这些程序对象的串行信息。本发明通过提供程序对象定义中每一改变的独特的“版本”识别,并提供能适应将串行或解串行的程序对象的特定版本的串行化和解串行特征,从而克服了该难题。
B.串行化图3表示在一个基本版本适应过程中的步骤,用于按照程序对象版本产生表示程序对象的串行信息。在该特定过程中,步骤110含有程序对象的版本,步骤120按照版本确定程序对象的表示,和步骤130产生传送这个表现的串行信息。该特定过程能用多种方法实现,但是,在优选的实施方案中,将被串行化的程序对象必须是定义实现串行化过程的多种功能的类的实例。这种类被认为是“可串行的”类。
图4提供这种基本串行化过程的特定实现的附加的细节。在特定实现中,要被串行化的程序对象的类定义取得程序对象版本的方法。步骤101实例化这个类的一个程序对象,和步骤110激活取得程序对象版本标识的适当方法。步骤121识别应被包括在程序对象串行的表示中的程序对象版本的属性。这可通过不同方式来执行,例如,将要串行程序对象的方法,在某种程度上与要被串行化的程序对象有关的另一类中的程序对象的方法,或一个属性的数据库。在任何情况下,一个决定串行属性的程序的实现,可被认为是程序对象类和版本的一个函数。步骤122确定要串行化的每一属性的值,和步骤130产生传送程序对象类和版本的串行化信息,和在步骤121,122中被识别的各个属性的表示。
图7所示的是一个可用来生成表示一个或多个程序对象的串行信息的过程的结构。按照这个过程,步骤131把要串行的程序对象的数量写进一个信息串行流中。为将串行的每个程序对象,步骤132将各个程序对象的类标识写入串行信息流中,和步骤133写各个程序对象的版本标识。
对于将被串行化的各个程序对象的各个属性,步骤134激活适当的过程来串行各个属性。步骤134能执行一个递归的程序来串行程序对象属性,它们自身是可串行的一个或多个程序对象。该功能在下文中将有详细描述。步骤135决定是否各个程序对象的全部属性都已被串行化,如果没有,此过程返回步骤134来串行下一个属性。
当各个程序对象的全部属性都串行了,该过程继续步骤136,决定各个程序对象的类是否派生于应被串行化的基本类。图9所示的是一个可能在应用程序中使用符合Sun Microsystems公司提供的JAVA开发包(JDK)版本1.1的“JavaBeansTMAPI标准”版本1.01的程序对象来执行步骤136过程中的步骤,该标准包括一个所谓“JavaBeans”的串行程序元件的标准,可参照http//java.sun.com/products/jdk/1.1/docs/guide/beans/index.html,在此作为参考。
图9所示的实现利用Java编程语言中叫做反射的特征。步骤361激活程序对象的一个方法来获取程序对象作为实例的类的名称。步骤362识别与要串行的程序对象相关的对象-描述符类的类名称。在一个优选的实施方案中,对象-描述符类的类名称派生于程序对象的类的名称,以例如,附加串式“描述符”给类名称的方式实现。在该示例中,类“Widget”的对象-描述符的类名称是“WidgetDescriptor”。步骤363实例化一个对象-描述符类的对象和步骤364激活由Java反射应用程序编程接口(API)提供的一个方法,从而获取对象-描述符从中派生的基本类的名称。该功能在下文中将有详细描述。
如果这个对象-描述符类从一个对象-描述符基本类派生,处理程序将继续步骤133把一个附属于基本类的版本标识写入串行信息流。通过串行那个基本类的适当属性处理该过程将继续下去。该过程重复直至步骤136确定没有剩余的基本类,此时步骤137是否还有余下的程序对象要串行。如果是这样,步骤132为下一个单独的程序对象继续。否则,程序在步骤138结束。
图11所示的是派生程序对象类的层次和相关的对象-描述符类的层次之间的关系。程序对象类C1到C5分别由方框381到385表示,对象-描述符类C3Descriptor,C4Descriptor和C5Descriptor分别由方框483到485表示。类C5从类C4派生,而类C4从类C3派生。在所示实例中,类C3是被认为是Xserializable的最高级程序对象类。该特定实现中的Xserializable指明可被串行化的程序对象类的实例,因为该类利用对象串行化的实现属性。类C5Descriptor派生自类C4Descriptor的对象-描述符类,而类C4Descriptor派生自C3Descriptor。每一个对象-描述符类实现能被激活从而获取各个程序对象类的描绘性信息的方法。这些信息能为各个类串行化程序对象。
例如,对象-描述符类C4Descriptor的对象的一个方法能被激活去取得要被串行化的类C4的属性列表。对于用Java编程语言的实现,Java反射机制的特征能应用在对象-描述符类的方法以取得这个信息。因为类C3是可XSerializable的最高级程序对象类,没有为较高级对象-描述符类C2和C1定义对应程序对象类。
C.串行信息格式原则上讲,串行信息可被排列成任何格式。在本发明中特定格式无关紧要。按照上文提到的过程,图10显示的是串行信息流300的内容原理图解。按照所示格式,段301提供由信息流中的信息表示的程序对象的数量的标识,段302和303分别的提供在信息流中表示的第一个程序对象的类名称和版本标识,和段304传送表示第一个程序对象的一个或多个属性的串行信息。
如果第一个程序对象类是由串行了的基本类派生的,段305和306表示基本类的版本和属性。如果这个基本类派生自一个或多个附加的串行的基本类,附加的段对给将被用来给每个基本类的版本和属性传送信息。
如果串行信息流300表示不只一个程序对象,第二个程序对象的表示将从段307开始,这给第二个程序对象提供了类名称的标识。与信息在段302至306为第一程序对象传递相同的方式,附加段传递第二个程序对象的信息和任何后继的程序对象。
如段304这样传递表示一个或多个串行的属性的段在需要时可被分成信息单元。例如,在段中表示多个属性的信息可被分成每个属性一个独立的单元。那些本身是可串行对象的属性,单元可能被进一步分成段。例如,如果段304传送表示多个可串行对象的信息,此段中的信息可能按照图10所示的段301到307的格式来划分。
D.解串行图5代表从表示类的可能的不同版本的程序对象的串行信息上建立的类的特定版本的程序对象的基本过程。在该特定过程中,步骤210读串行信息来取得串行信息代表的程序对象的版本,和步骤220按照串行信息代表的类版本和要建立程序对象类的版本给程序对象的属性确立值。该特定过程可由不同的方式实现;但是,在优选的实施方案中,要串行的程序对象一定是一个可串行的类的实例,因为该类定义实现串行化过程的不同功能。
图6提供的是给此基本解串行过程的一个特别的实现的附加细节。在该实现中,在步骤210读串行信息来取得由串行信息代表的程序对象版本的标识之前,步骤201实例化一个程序对象。在另一个实施例中,一个程序对象的实例可能在一个后继步骤中建立。步骤221识别在串行信息中包含的程序对象版本的属性。这可由不同的方式实现包括,例如要解串行的程序对象的一个方法,与要解串行的程序对象类以某种方式相关的类中程序对象的一个方法,或一个属性数据库。在任何情况下,决定要解串行属性的过程的实现可当作程序对象类和版本的一个函数。步骤222从串行信息中获取一个或多个属性的值,和步骤223为程序对象新建的实例的相应属性确立值。
图8所示的是代表一个或多个程序对象的用来读和处理串行信息的一个处理过程的结构。按照该过程,步骤231读串行信息来取得串行信息代表的程序对象数量。对于每个要解串行的程序对象,步骤232从串行信息中读各个程序对象类的一个标识,和步骤223读各个程序对象的版本的标识。
对于各个要解串行的程序对象的每个属性,步骤234激活适当的过程以解串行各个属性。步骤234可实现一个递归过程解串行自身是可解串行的一个或多个程序对象的程序对象属性。下文将会详述该功能。步骤235确定是否各个程序对象的全部属性都已解串行了,如果没有,此程序转回步骤234解串行下一个属性。
当各个程序对象的所有属性都已解串行了,处理程序继续步骤236决定是否各个程序对象的类是源于应被解串行的任何基本类。图9示出在使用符合Java对象串行化标准的应用程序中执行步骤236的处理过程的步骤。上文提到的该特定实现利用Java编程语言中叫做反射的特性。
如果这个类派生自一个基本类,处理程序继续步骤233,在串行信息中读附属于基本类的版本的标识。处理过程继续解串行此基本类的适当属性。此程序将重复直到步骤236决定再没有剩余的基本类了,此时步骤237确定是否还有任何剩余的程序对象要串行。如果是,处理过程继续下一个程序对象执行步骤232。否则,处理过程在步骤238结束。
E.实现1.串行化a)高级例程以下几个程序片段说明上文提到的处理过程的各个方面的实现。这些程序片段在包括Java编程语言的语法特性的伪代码中表达。在此提供的程序片段并不用于适合编译成为一个实际的具体实现而是为阐明可能的实现。例如,这些程序片段不包括实践中要求的对错误状态和例外的检验。进一步讲,尽管很多个别叙述是由符合不同的Java规范和技术要求的实现组成,本发明可用任何编程语言实现;然而,Java语言提供用于以下特定实现的特性,如反射API。
以下程序片段实现可用来串行一个或多个程序对象的serializeObjects步骤。
public void serialize(ObjectOutputStream out,Vector objects) {int nObjects=0Object[ ]objArry=newObject[objects.sizeO];Objects.copyInto(objArry);for(int I=0;i<objArry.length;i++) {Object o=objArry[i];if(o instanceof Xserializable)nObjects++;}out.wirteInt(nObjects);∥写对象for(int I=0;i<objArry.length;i++) {Object o=objArry[i];if(o instanceof Xserializable)SerializeObject(out,(Xserializable)o);}在该实现中,例程serializeObjects接收识别一个或多个串行的程序对象的一个objects阵列,并接收识别要被写入串行信息的串行流的引用out。该步骤使用变量nObjects计算在阵列objects中代表的能被串行化的对象的数量。如上所述,在该特定实现中的Xserializable指示出能被串行化的程序对象,因为程序对象属于利用对象串行化实现特性的类。对象计数nObjects写入串行流out。该例程中的for循环重复调用serializeObject例程来串行每个被指定为Xserializable的object阵列中识别的程序对象。
b)低级步骤以下程序片段执行由例程serializeObjects调用的例程serializeObject来串行程序对象。该例程串行程序对象的特定属性,包括程序对象类从中派生出来的任何基本类的属性。一个属性可以是一个单一实体如一个整数,或者是实体的一个阵列。如果一个属性自身是一个可串行的程序对象或一个可串行的程序对象的阵列,递归调用serializeObject以串行这些程序对象。Private void serializeObject(ObjectOutputStream out,XSerializable obj){String className=obj.getClass( ),getName( );ObjectDescriptior desc=(ObjectDescriptor)Class.forName(ciassName +“Descriptor”).newInstance( );Vector temp=new Vector( ); ∥上升描述符类级temp.addElement(des.getClass( ));while((c=c.getSupterclass( ))!=null)temp.addElement(c);out.writeUTF(className); ∥写类名称Class[ ]descriptors=new Class[temp.size( )];Temp.copyInto(descriptors);for(int i=0;i<descriptors.length;i++) {∥为每个描述符类Object descObj=descriptors[i].newInstance( );ObjectDescriptor descriptor=(ObjectDescriptor) descObj;Class targetClass=Class.forName(descriptor.getClassName( ));Object targetObj=targetClass.newInstance( );if(targetObj instanceof XSerializable) {float version =((XSerializable)targetObj).getXClassVersion( );out.writeFloat(version);∥写对象版本PropertyDescriptor[ ] props=descriptor.getProperties(version);for(int j=0;j<props.length;j++) {∥使用映象读对象属性以串行化String funcName=“get”+Character.toUpperCase(props[j].name.charAt(0))+props[j].name.substring(1);Class[ ]args=new Class
;Method m targetClass.getMethod(funcName,args);if(m!=null) {Object[ ]params=new Object
;Object ret Val=m.invoke(obj,params);if(retVal instanceof XSerializable) ∥写属性this.serializeObject(out,(XSerializable)retVal);else if(retVal instanceof XSerializableArry) {
XSerializable[ ]data=(XSerializableArray)retVal).getObjects( );if(data!=null){ ∥写长度和对象out.writeInt(data.length);for(int h=0;h<data.length;h++)this.serializeObject(out,data[h]);}elseout.writeInt(0);∥写零长度}else if(retVal instanceofByteArrayWrapper){byte[ ]data=((ByteArrayWrapper)retVal).getBytes( );if(dat!=null){out.writInt(data.length);∥写字节阵列长度out.write(data);}elseout.writeInt(0);∥写零长度else if(retVal instanceofIntArrayWrapper){int[ ]data=((IntArrayWrapper)retVal).getInts( );if(data!=null){ ∥写零和整型阵列out.writeInt(data.length);for(int h=0;h<data.length;h++)out.writeInt(data[h]);}else
out.writeInt(0);∥写零长度}elseout.writObject(retVal);∥写对象}}}}在该实现中,例程serializeObject接收一个可串行的对象的引用obj和一个已串行化的的表示要写入的串行流的引用out。该例程获取对象类的名称并把类名称写进串行流out。该例程还建立一个类的阵列descriptors。该阵列的第一个元素是附属于将被串行化的程序对象的对象-描述符的类。阵列中后继的入口,如果有,是对象-描述符类从中派生的基本类。
该例程在descriptors阵列中重复for循环。对每个阵列中的描述符类,该类的一个各个对象-描述符对象被实例化为descriptor并被用来标识各个对象-描述符对象描述的程序对象的目标类。例如,从阵列descriptor实例化的第一个对象-描述符对象的目标类是要被串行化的程序对象obj的类。如果该目标类的一个对象被认为是XSerializable的,该例程通过取得目标类版本的标识和把这个版本标识写进串行流out中而继续。对象-描述符对象的getProperties方法此后被激活从而取得每一个元素描述要串行的属性的props阵列。因为getProperties方法是对象类版本的一个函数,实现该方法的例程会不同,识别串行属性的过程会被认为是对象类和对象类版本两者的函数。
该例程在props阵列中重复for循环。对于阵列中的每个属性描述符,Java中的反射机制用来取得对应属性。如果该属性被指定为Xserializable,循环调用例程serializeObject来串行这个对象。如果这个属性是一个指定的Xserializable的元素阵列,阵列data将为这些元素建立,这个阵列的长度写在串行流out中,和为阵列中的任一元素都递归调用serializeObject。如果这个属性是字节阵列或整数阵列,阵列的长度和阵列中每个元素的表示要写入串行流out。否则,这个属性本身的一个表示会写入串行流out。
2.解串行a)高级步骤以下程序片段实现deserializeObjects,调用该例程实现一个或多个程序对象解串行。
public Vector deserializeObjects(ObjectInputStream in){vector objects=new Vector( );int nObjects=in.readInt( );∥读串行化对象数for(int i=0;i<nObjects;i++) {∥读每个对象Object o=deserializeObject(in);if(o!=null)objects.addElements(o);}}在该实现中,例程deserializeObjects接收从一个或多个要解串行的程序对象中的串行表示中识别一个串行流的引用in。该例程将在串行流中表示对象的数量读入nObjects。该例程中的for循环重复调用例程deserializeObject来解串行串行流中代表的每个程序对象。
b)低级步骤以下程序片段实现deserializeObjects例程,调用例程deserializeObject来解串行程序对象。该例程解串行程序对象的特定属性,包括可能从程序对象类从中派生的基本类的实现。属性可以是一个单一实体如一个整数,或是一个实体阵列。如果一个属性本身就是一个程序对象或一个程序对象的阵列,要用deserializeObject的递归调用来解串行这些程序对象。
private Object deserializeObject(ObjectInputStream in){Object obj=null;String className=in.readUTF( );∥读对象类名称∥为类取得对象描述符ObjectDescriptor desc=(ObjectDescriptor)Class.forName(className+“Descriptor”.newInstance( );Class objClass=Class.forName(desc.getClassName( ));Obj=objClass.newInstance( );∥上升描述符类级
Vector temp=new Vector( );temp.addElement(desc.getClass( ));Class c=desc.getClass( );while((c=c.getSupterclass( ))!=null)temp.addElement(c);Class[ ]descriptors=new Class[temp.size( )];Temp.copyInto(descriptors);for(int i=0;i<descriptors.length;i++) { ∥为每个描述符Class d=descriptors[i];Object theobj=d.newInstance( );float version=in.readfloat( ); ∥读对象版本ObjectDescriptor objDesc=(ObjectDescriptor)theObj;PropetyDescriptor[ ]props=objDesc.getProperties(version);Class[ ]args=new Class[1];for(int j=0;j<props.length;j++){Object prop Val=null;if(is XSerializable(props[j].type))prop Val=null;else if(props[j].type.getName( ) ==“XSerializableArray”){int length=in.readInt( );∥读字节阵列长度XSerializable[ ]data=newXSerializable[length];for(int h=0;h<data.length;h++)data[h] =(XSerializable)deserializeObject(in);prop Val=new XSerializableArray(data);}else if (props[j].type.getName( ) ==“ByteArrayWrapper”){int length=in.readInt( ); ∥读字节阵列长度byte[ ]data=new byte[length];in.readFully(data,0,length);prop Val=new ByteArrayWrapper(data);}else if(props[j].type.getName( )==“IntArrayWrapper”){int length=in.readInt( ); ∥读字节阵列长度int[ ]data=new int[length];for(int h=0;h<data.length;h++)
data[h]=in.readInt( );prop Val=new IntArrayWrapper(data);elseprop Val=in.readObject( );args
=props[j].type; ∥激活方法以设置属性String funcName=“set”+Character.toUpperCase(props[j].name.charAt(0))+props[j].name.substring(1);Method m=objClass.getMethod(funcName,args);if(m!=null){Object[ ]params=new Object[1];Params
=prop Val;m.invoke(obj,params)”}}}return obj;}在该实现中,例程deserializeObject接收识别一个将被解串行的程序对象的串行表示的串行流引用in。该例程串行流in中读对象的类名称。该例程还会建立一个对象-描述符类的阵列descriptors。阵列的第一个元素是附属于在串行流中读到的类的对象-描述符。阵列中的后继入口,如果有,是对象-描述符类从中派生的基本类。
该步骤用一个在阵列descriptors中重复for循环。对于阵列中每个描述符类,各个版本标识在串行流in中读出,该类的各个对象-描述符对象被实例化为objDesc,要解串行的各个对象程序对象被例示为theObj。对象-描述符对象objDesc的方法getProperties被激活来取得每个元素描述在串行流中表示的将被解串行的属性的props阵列。该方法是从串行流in中读到的各个版本标识的函数。如以上所述,要解串行的属性的决定可能被认为是目标对象类和版本两者的函数。
该例程继续在props阵列中重复for循环来解串行每个属性。如果属性本身被指定为XSerializable,例程deserializeObject被递归调用以解串行这个对象。如果这个属性是一个被指定为XSerializable的元素阵列,阵列的长度在串行流in中读出,建立一个data阵列,然后例程deserializeObject被递归把每个属性解串行成data阵列的各个元素。如果这个属性是字节阵列或整数阵列,阵列的长度在串行流in中读出,建立一个data阵列,每个属性在串行流中读出并被放进data阵列的各个元素中。到目前为止我们讨论过的每一种类型的属性,串行流in中取得的属性的表示被放进一个称为propVal的对象中。如果这个属性不是上文提到的类型,从串行流out中读出属性值并直接放进变量propVal。被解串行的程序对象的一些适当方法然后被激活从而基于propVal的表示以建立程序对象属性。
3.其他方面a)测试XSerializable以下程序片段实现例程isXSerializable,以上程序片段用它确定特定类是否是XSerializable的。
private boolean isXSerializable(Class c){Class[ ]interfaces=c.getInterfaces( );for(int I=0;I<interfaces.length;I++){if(interfaces[I].getName( )==“XSerializable”)return true;}class superClass=c;while((superClass=superClass.getSuperclass( ))!=null){interfaces=superClass.getInterfaces( );for(int I=0;I<interfaces.length;I++){if(interfaces[I].getName( )==“XSerializable”)return true;}}return false;}在该实现中,例程isXSerializable接收类c并决定作为类的实例的对象是否是XSerializable。如果类c本身有所示特定名称的接口,这个类被认为是XSerializable。如果不是,生类c从中派生的基本类被测试来决定是否所有基本类实现该接口。如果某个基本类实现该接口,类c被认为是XSerializable。否则,类c不被认为是XSerializable。
b)串行化开发包上文说明的程序片段和任何必要的属性能很便利的作为一个特殊类的方法来实现。以下程序片段讲述如何实现它们。
public class XserializableKit{∥串(并)行化可串行化对象的类public XserializableKit( ){}∥包的属性和方法}c)可串行化的程序对象类以下程序片段描述一个可Xserializable类按照上文提到的实现被定义。第一个示例说明版本1.0的类定义。
public class Widget implements Xserializable{private static Float_ver=1.0f;private String_name=“”;public Float getXClassVersion( ){return_ver;}public void setName(String name){_name=name;}}第二个示例说明版本1.1的类定义。
public class Widget implements Xserializable{private static Float_ver=1.1f;private String_name=“”;private Color_color=“”;public Float getXClassVersion( ){return_ver;}public void setName(String name){_name=name;}public void setColor(Color color){}}在该实现中,属性_name和_color方法setName和setColor是任意的。这些方法在下面讨论的实例中会用到。
一个可Xserializable类可扩展另一个可Xserializable基本类。它还可以包括或嵌入引用一个Xserializable类的实例的属性。
简单类型如“字节”和“整数”的阵列可以以不同方式作为Xserializable结构实现。以下程序片段说明与上文论及的实现一致的一个实现的实例。该片段定义字节阵列和整数阵列的两个包装。
public class ArrayWrapper implements XSerializable{private static Float_ver=1.0f;Byte byteArray;Int[ ]intArray;public ArrayWrapper{}public Float getXClassVersion( ){return_ver;}public void setByteArray(ByteArrayWrapper wrapper){return new ByteArrayWrapper(byteArray);}public void setIntArray(IntArrayWrapper wrapper){intArray=wrapper.getInts( );}public IntArrayWrapper getIntArray( ){return new IntArrayWrapper(intArray);}}d)对象-描述符类以下程序片段描述一个对象-描述符类按照上文提到的实现被定义。
public class WidgetDescriptor implements ObjectDescriptor{private String targetClass=“X.Widget”;public WidgetDescriptor( ){}public String getClassName( ){return targetClass;}public PropertyDescriptor[ ]getProperties(Float version){PropertyDescriptor[ ]array=null;if(version==1.0f){array=new PropertyDescriptor[1];array
=newPropertyDescriptor(“name”,java.lang.String.TYPE);}elseif(version==1.1f) }array=new PropertyDescriptor[2];
array
= newPropertyDescriptor(“name”,java.lang.String.TYPE);array[1] = newPropertyDescriptor(“color”,java.awt.Color.class);}return array;}以下程序片段描述一个对象-描述符类任何被上面的ArrayWrapper类定义。
public class ArrayWrapperDescriptor implements ObjectDescriptor{private String targetClass=“ArrayWrapper”;public ArrayWrapperDescriptor( ){}public String getClassName( ){return targetClass;}public PropertyDescriptor[ ]getProperties(Float version){PropertyDescriptor[ ]array=null;if(version==1.0f){array=new PropertyDescriptor[2];array
= newPropertyDescriptor(“ByteArray”,Class.forName.(“ByteArrayWrapper”));array[1] = newPropertyDescriptor(“IntArray”,Class.forName.(“IntArrayWrapper”));}return array;}e)应用程序示例以下程序片段展示一个应用程序如何使用以上串行化开发包串行一个或多个程序对象。在这个示例中,Widget类的版本1.0的两个程序对象实例被串行化到test.ser文件夹。
public class Examplel{public static void main(String[ ]args){Widget widObj1=new Widget( );Widget widObj2=new Widget( );WidObj1.setName(“test1”);WidObj2.setName(“test2”);Vector vecObj=new Vector( );VecObj.addElement(widObj1);
VecObj.addElement(widObj2);XSerializationKit kit=new XSerializationKit( );ObjectOutputStream out=newObjectOutputStream(newFileOutputSteam(“test.ser”);kit.serializeObjects(out,vecObj);∥串行化对象out.close( );}}以下程序片段展示一个应用程序如何使用上述串行化开发包串行化开发包解串行一个或多个程序对象。在这个示例中,Widget类中的两个实例在由Example1应用程序生成的test.ser文件中解串行。应用程序Example2创建符合Widget类版本1.1的程序对象,如程序片段中最后一行显示的激活setColor方法设定程序对象widObj1的色彩属性。如上所示,该属性是加到Widget类定义的版本1.1上的。
public class Example2{public static void main(String[ ]args){XSerializationKit kit=new XSerializationKit( );ObjectInputStream in=newObjectInputStream(newFileInputSteam(“test.ser”);Vector vecObj=(Vector)kit.deserializeObjects(in);in.close( );Widget widObj 1=(Widget)vecObj
;Widget widObj 2=(Widget)vecObj[1];WidObj1.setColor(Color.red);}}
权利要求
1.一种串行化作为对象类实例的程序对象的方法,其中该方法包括获取程序对象的版本标识,和产生传递被确认为对象类和版本标识的函数的程序对象的表示的串行化信息。
2.如权利要求1的方法,其中对象的表示决定于标识一个或多个要被串行化的程序对象的属性,其中按照对象类和程序对象版本的标识来识别属性。确定要被串行化的程序对象的各个属性的值;和产生对象的表示以包括对象类的名称的表示,程序对象的版本标识,和要被串行化的各个属性的值。
3.如权利要求2的方法,其中要被串行化的程序对象的一个或多个属性通过激活一个描述对象类的实例怎样被串行化的对象-描述符接口中的一个例程来标识,其中该例程响应程序对象的版本标识。
4.如权利要求3的方法,其中对象-描述符接口有派生于对象类名称的名称。
5.如权利要求3的方法,其中程序对象和程序类符合Java编程语言的JavaBean标准。
6.如权利要求2的方法,其中要被串行化的程序对象的一个或多个属性通过激活一个返回按照对象类和版本标识而变化的属性名称列表的例程来识别。
7.如权利要求6的方法,其中该例程是一个定义要被串行化的程序对象的可串行化的特征的对象-描述符类的实例的对象的方法。
8.如权利要求2的方法,其中版本标识是通过激活程序对象的一个方法取得的;要被串行化的程序对象的一个或多个属性通过激活一个作为对象类和程序对象的版本标识的函数的对象-描述符对象的方法来识别;和串行信息通过激活输出流对象的一个方法产生。
9.一个用来串行是作为对象类的实例的程序对象的装置,其中该装置包括随机访问存储器;和连接到随机访问存储器的处理电路,其中处理电路取得一个储存在随机访问存储器中的程序对象的版本标识并生成传递被认为是对象类和版本标识的函数的程序对象的表示的串行信息。
10.如权利要求9中的装置,其中这个对象的表示取决于识别要被串行化的程序对象的一个或多个属性,其中这些属性是根据对象类和程序对象版本的标识来识别的。确定要被串行化的程序对象的各个属性的值;和产生对象的表示来包括对象类的名称的表示,程序对象的版本标识,和要被串行化的各个属性的值。
11.如权利要求10中的装置,其中要被串行化的的程序对象的一个或多个属性通过激活描述被串行化的对象类如何被串行化的对象-描述符接口中的一个例程来识别,其中该例程响应程序对象的版本标识。
12.如权利要求11中的装置,其中对象-描述符接口有派生于对象类名称的名称。
13.如权利要求11中的装置,其中程序对象和程序类符合Java编程语言的JavaBean标准。
14.如权利要求10中的装置,其中要被串行化的程序对象的一个或多个属性通过激活一个返回按照对象类和版本标识变化的属性名称列表的例程来识别。
15.如权利要求14中的装置,其中该例程是一个定义要被串行化的程序对象的可串行化的特征的对象-描述符类的实例的对象的方法。
16.如权利要求10中的装置,其中版本标识是通过激活程序对象的一个方法取得的;要被串行化的程序对象的一个或多个属性通过激活一个作为对象类和程序对象的版本标识的函数的对象-描述符对象的方法来识别;和串行信息通过激活输出流对象的一个方法而产生。
17.一种媒介,由一个装置可读并传递由该装置执行的程序指令以执行串行化作为对象类的实例的一个程序对象的方法,其中该方法包括获取程序对象的版本标识,和产生传递被确认为对象类和版本标识的函数的程序对象的表示的串行的信息。
18.如权利要求17的媒介,其中对象的表示取决于标识要被串行化的程序对象的一个或多个属性,其中按照对象类和程序对象版本的标识来识别属性。确定要被串行化的程序对象的各个属性的值;和产生对象的表示以包括对象类的名称的表示,程序对象的版本标识,和要被串行化的各个属性的值。
19.如权利要求18的媒介,其中要被串行化的程序对象的一个或多个属性通过激活描述被串行化的对象类怎样被实例化的对象-描述符接口这的一个例程来识别,其中该例程响应程序对象的版本标识。
20.如权利要求19的媒介,其中对象-描述符接口有派生自对象类名称的名称。
21.如权利要求19的媒介,其中程序对象和对象类符合Java编程语言的JavaBean标准。
22.如权利要求18的媒介,其中要被串行化的程序对象的一个或多个属性通过激活一个返回按照对象类和版本标识变化的属性名称列表的例程来识别。
23.如权利要求22的媒介,其中该例程是一个定义要被串行化的程序对象的可串行化的特征的对象-描述符类的实例的对象的方法。
24.如权利要求18的媒介,其中版本标识是通过激活程序对象的一个方法取得的;要被串行化的程序对象的一个或多个属性通过激活一个作为对象类和程序对象的版本标识的函数的对象-描述符对象的方法来识别;和串行信息通过激活输出流对象的一个方法而产生。
25.一种解串行传递作为对象类的实例的程序对象的表示的串行化信息的方法,其中该方法包括在串行信息中取得对象类和程序对象的版本标识,和从串行化的信息中为一个或多个对象属性确立值,其中这些一个或多个属性的值被确立为对象类的和版本标识的函数。
26.如权利要求25的方法,其中为一个或多个属性的值取决于标识要被解串行的的程序对象的一个或多个属性,其中这些属性是根据对象类和程序对象版本的标识来标识的。为要被解串行的程序对象的一个或多个属性从串行信息中获取值;和响应从串行信息中获取的值,为程序对象的一个或多个属性确立值。
27.如权利要求26的方法,其中要被解串行的一个或多个属性通过激活描述被解串行的对象类如何被实例化的对象-描述符接口中的一个例程来标识,其中该例程响应程序对象的版本标识。
28.如权利要求26的方法,其中对象-描述符接口有派生自对象类名称的名称。
29.如权利要求27的方法,其中程序对象和对象类符合Java编程语言的JavaBean标准。
30.如权利要求26的方法,其中要被解串行的程序对象的一个或多个属性通过激活一个返回按照对象类和版本标识变化的属性名称列表的例程来识别。
31.如权利要求30的方法,其中该例程是一个定义要被解串行的程序对象的可解串行的特征的对象-描述符类的实例的对象的方法。
32.如权利要求26的方法,其中版本标识是通过激活输入流对象的一个方法取得的;和要被解串行的程序对象的一个或多个属性通过激活一个作为对象类和程序对象的版本标识的函数的对象-描述符对象的方法来识别。
33.一种解串行传递作为对象类的实例的程序对象的表示的串行化信息的装置,其中该装置包括随机访问存储器;和连接到随机访问存储器的处理电路,其中处理电路从串行信息中取得对象类和程序对象的版本标识,并从串行信息在随机访问存储器中建立该对象的一个或多个属性的值,其中一个或多个属性的值作为对象类和版本标识的一个函数而建立。
34.如权利要求33中的装置,其中为一个或多个属性的值取决于标识要被解串行的的程序对象的一个或多个属性,其中这些属性是根据对象类和程序对象版本的标识来标识的。为要被解串行的程序对象的一个或多个属性从串行信息中获取值;和响应从串行信息中获取的值,为程序对象的一个或多个属性确立值。
35.如权利要求34的装置,其中要被解串行的一个或多个属性通过激活描述被解串行的对象类如何被实例化的对象-描述符接口中的一个例程来标识,其中该例程响应程序对象的版本标识。
36.如权利要求34的装置,其中对象-描述符接口有派生自对象类名称的名称。
37.如权利要求35的装置,其中程序对象和对象类符合Java编程语言的JavaBean标准。
38.如权利要求34的装置,其中要被解串行的程序对象的一个或多个属性通过激活一个返回按照对象类和版本标识变化的属性名称列表的例程来识别。
39.如权利要求38的装置,其中该例程是一个定义要被解串行的程序对象的可解串行的特征的对象-描述符类的实例的对象的方法。
40.如权利要求34的装置,其中版本标识是通过激活输入流对象的一个方法取得的;和要被解串行的程序对象的一个或多个属性通过激活一个作为对象类和程序对象的版本标识的函数的对象-描述符对象的方法来识别。
41.一种媒介,由一个装置可读并传递由该装置执行的程序指令以进行解串行传递作为对象类的实例的程序对象的表示的串行化信息的方法,其中该方法包括在串行信息中取得程序对象的对象类和版本标识,和从串行化信息中为一个或多个对象属性确立值,其中一个或多个属性的值被确立为对象类和版本标识的函数。
42.如权利要求41的媒介,其中为一个或多个属性的值取决于标识要被解串行的的程序对象的一个或多个属性,其中这些属性是根据对象类和程序对象版本的标识来标识的。为要被解串行的程序对象的一个或多个属性从串行信息中获取值;和响应从串行信息中获取的值,为程序对象的一个或多个属性确立值。
43.如权利要求42的方法,其中要被解串行的一个或多个属性通过激活描述被解串行的对象类如何被实例化的对象-描述符接口中的一个例程来标识,其中该例程响应程序对象的版本标识。
44.如权利要求42的媒介,其中对象-描述符接口有派生自对象类名称的名称。
45.如权利要求43的媒介,其中程序对象和对象类符合Java编程语言的JavaBean标准。
46.如权利要求42的媒介,其中要被解串行的程序对象的一个或多个属性通过激活一个返回按照对象类和版本标识变化的属性名称列表的例程来识别。
47.如权利要求46的媒介,其中该例程是一个定义要被解串行的程序对象的可解串行的特征的对象-描述符类的实例的对象的方法。
48.如权利要求42的媒介,其中版本标识是通过激活输入流对象的一个方法取得的;和要被解串行的程序对象的一个或多个属性通过激活一个作为对象类和程序对象的版本标识的函数的对象-描述符对象的方法来识别。
49.一种媒介,由一个设备可读并传递表示作为对象类的实例的一个或多个程序对象的串行信息,其中串行信息包括由串行信息表示的程序对象的数量的标识;一个对象类名称的标识;和对于每个由串行信息表示的各个程序对象,各个程序对象的版本标识和各个程序对象的一个或多个属性的值。
50.如权利要求49媒介,传递表示作为对象类的超类的实例的一个或多个第二程序对象的串行信息,其中串行信息为每个第二程序对象包括第二程序对象的版本标识和各个第二程序对象的一个或多个属性的值。
51.一种媒介,由一个装置可读并传递由该装置执行的一个或多个程序指令以进行串行化或解串行作为程序对象的实例的程序对象的方法,其中一个或多个程序指令包括包括用来获取各个程序对象的版本标识的方法的对象类的定义;和包括用来标识要串行或解串行的各个程序对象的一个或多个属性的方法的对象-描述符类的定义。
52.如权利要求51的媒介,其中对象-描述符类的定义包括给要串行或解串行的各个程序对象的一个或多个属性返回名称标识的方法。
53.如权利要求51的媒介,其中对象-描述符类的定义包括给对象类返回名称的方法。
54.如权利要求51的媒介,其中一个或多个程序指令包括一个属性-描述符类的定义,它包括为要串行或解串行的各个程序对象的一个或多个属性获取属性类型的标识的方法。
全文摘要
为产生串行信息来代表程序对象(串行化)和在串行信息中重建程序对象(解串行)的已知技术在对程序对象的类结构和定义的改变上常有局限性。类结构的许多改变引起的不可兼容性阻碍程序对象的一个版本在代表程序对象的不同版本的串行信息中被复原。在此公开的技术通过允许串行化和解串行的过程按照程序对象的版本而有适应性从而克服了这一困难。
文档编号G06F9/44GK1290889SQ0013055
公开日2001年4月11日 申请日期2000年9月30日 优先权日1999年9月30日
发明者H·海斯特曼, 李家欣 申请人:精工爱普生株式会社
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1