《Object Serialization Stream Protocol》是Java进行序列化对象时的规范。html
1、流的格式(协议)要知足如下的设计目标java
●流紧凑而有结构,能高效的读取数组
●在读取的时候,能经过流的结构和格式实现跳读。而不用读取处理每个字节。缓存
●只要保存数据,而不包含类的信息(字节码)oracle
2、流基本结构元素编码
须要一个基本结构能在流中表明对象。对象的每个属性都要能有体现:对象的所属的类,对象的字段,能被特定方法写和读的数据(writeObject、readObject)。在流中对象组合要使用语法描述。流中有null、new 、classes、arrays、strings以及引用(references)有特殊的表述。每一个对象都被分配一个handle,handle用于引用(其余对象引用该对象)。handles 从0x7E0000开始顺序分配。当流被重置时,handle也要重新开始记数。spa
class 对象使用ObjectStreamClass 体现。设计
ⅰ、当ObjectStreamClass 表明的是非动态代理类时有如下特色:代理
●、在流中每一个class对象都有一个SUID( Stream Unique Identifier)code
●、要设置多个标识用来表示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 thewriteObject
method followed by anendBlockData
code.
一个类中全部基本类型数据字段值都会缓存并封装写在一个块数据记录中,不管是用writeObject
方法仍是writeObject
之外的方式(类没有writeObject
时的基本类型值)直接写入到流中。这些数据能被相应的readObject
方法或直接从流中读取(没有readObject
的类)。writeObject
序列化对象时会结束上一个块数据记录,并记录合适的对象,或记录object对象,或记录null对象、或记录引用前对象。块数据在进行校对时能够抛弃任意数据。当一个类在读取流内容时,流能够放弃任何数据或对象直到endBlockData标签。
3、流协议版本
从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
4、流格式的语法
下表包含了流格式的语法。非终结符使用斜体,终结符使用等宽体。非终结符紧跟着 ":",对应的定义人若是是可选的则使用分隔线分隔。以下:
符号 | 定义 |
(datatype) | 代表数据类型 |
token[n] | 取在已经定义好的token列表、指定位置的单词 |
x0001 | 16进制的表达 |
<xxx> | 代表一个数组的长度 |
注意:符号(utf) 用来指代一个使用2-byte长度的字符串,(long-utf) 用来指代使用8-byte记录长度的字符串。具体信息参考第二小节。
语法规则下一篇再讲
参考 http://docs.oracle.com/javase/7/docs/platform/serialization/spec/protocol.html
确定有错误,请指出