《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
確定有錯誤,請指出