Object Serialization Stream Protocol(对象序列化流协议)

《Object Serialization Stream Protocol》是Java进行序列化对象时的规范。

一、流的格式(协议)要满足以下的设计目标

●流紧凑而有结构,能高效的读取

●在读取的时候,能通过流的结构和格式实现跳读。而不用读取处理每一个字节。

●只要保存数据,而不包含类的信息(字节码)

二、流基本结构元素

需要一个基本结构能在流中代表对象。对象的每一个属性都要能有体现:对象的所属的类,对象的字段,能被特定方法写和读的数据(writeObject、readObject)。在流中对象组合要使用语法描述。流中有null、new 、classes、arrays、strings以及引用(references)有特殊的表述。每个对象都被分配一个handle,handle用于引用(其他对象引用该对象)。handles 从0x7E0000开始顺序分配。当流被重置时,handle也要从新开始记数。

class 对象使用ObjectStreamClass 体现。

       ⅰ、当ObjectStreamClass 代表的是非动态代理类时有以下特点:

             ●、在流中每个class对象都有一个SUID( Stream Unique Identifier)

             ●、要设置多个标识用来表示class是否定义了writeObject方法,是实现了serializable还是                               externalizable或者是枚举

             ●、该class可序列的字段数目

             ●、使用默认序列化方式的字段(String\array\object等),使用JVM规范的“field descriptor”                    e.g ,"Ljava/lang/Object;")

             ●、使用annotateClass方式可以写入任意大小的块数据记录或对象

             ●、记录父类的ObjectStreamClass,如果父类不能序列化使用null 表示。

       ⅱ、当ObjectStreamClass 代表的是动态代理类时有以下特点:

             ●、记录class 实现的接口数量

             ●、按getInterfaces 的顺序记录class实现的接口的名称

             ●、使用annotateProxyClass的方式写入任意大小的块数据和对象

             ●、记录class的父类,永远记录为 java.lang.reflect.Proxy 

String 对象由字符内容经过编码(utf-8改,与java.io.DataInput\readUTF and DataOutput\writeUTF)后的byte数据和btye数据长度组成。长度根据字符串的长度分为两种:如果小于65536 bytes 则用2byte 16bit 的无符号数表示长度,否则用8byte 64 bit 的有符号数表示。使用 typecode  表示不同的类型。

数组有以下的特点:

             ●、数组的ObjectStreamClass对象

             ●、元素的长度

             ●、数组保存的值,值的对象的类型使用数据的class对象,如byte array 的值的类型 是byte

Enum 枚举的体现:

             ●、enum type 的 ObjectStreamClass

             ●、enum 的枚举的名称string

New object 在流中的体现:(如果有谁知道这是什么请留言告诉我-_-||)

  • The most derived class of the object.
  • Data for each serializable class of the object, with the highest superclass first. For each class the stream contains the following:
    • The serializable fields.See Section 1.5, "Defining Serializable Fields for a Class."
    • If the class has writeObject/readObject methods, there may be optional objects and/or block-data records of primitive types written by the writeObject method followed by an endBlockData code.

一个类中所有基本类型数据字段值都会缓存并封装写在一个块数据记录中,无论是用writeObject 方法还是writeObject 以外的方式(类没有writeObject 时的基本类型值)直接写入到流中。这些数据能被相应的readObject 方法或直接从流中读取(没有readObject 的类)。writeObject 序列化对象时会结束上一个块数据记录,并记录合适的对象,或记录object对象,或记录null对象、或记录引用前对象。块数据在进行校对时可以抛弃任意数据。当一个类在读取流内容时,流可以放弃任何数据或对象直到endBlockData标签。

三、流协议版本

从JDK1.2开始流序列化和结构不再向下兼容。如果必须要兼容JDK1.2以下版本,可以通过指定流协议的版本号或得兼容。使用ObjectOutputStream.useProtocolVersion 指定流协议版本。

流协议主要有以下版本:

ObjectStreamConstants.PROTOCOL_VERSION_1:指定初始的流格式。

ObjectStreamConstants.PROTOCOL_VERSION_2:指定新的扩展的数据格式。基本类型数据是写在数据块中以TC_ENDBLOCKDATA 结尾

块数据得边界已经标准化的。基本类型的数据块要求不能超过1024kb大小。这个改变使得序列化数据格式的规格更加的紧凑了,这个改变是向后、向前兼容的。

JDK1.2 开始的默认使用流协议PROTOCOL_VERSION_2

JDK1.1 默认使用PROTOCOL_VERSION_1

JDK1.1.7以及更高版本已经能使用两个版本

JDK1.1.7之前的版本只能使用PROTOCOL_VERSION_1

 

四、流格式的语法

下表包含了流格式的语法。非终结符使用斜体,终结符使用等宽体。非终结符紧跟着 ":",对应的定义人如果是可选的则使用分隔线分隔。如下:

符号定义
(datatype)表明数据类型
token[n]取在已经定义好的token列表、指定位置的单词
x000116进制的表达
<xxx>表明一个数组的长度

注意:符号(utf) 用来指代一个使用2-byte长度的字符串,(long-utf) 用来指代使用8-byte记录长度的字符串。具体信息参考第二小节。

 

语法规则下一篇再讲

参考 http://docs.oracle.com/javase/7/docs/platform/serialization/spec/protocol.html

 

肯定有错误,请指出

 

 

 

 

转载于:https://my.oschina.net/u/2563693/blog/867088

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值