2015-04-02 120 views
1

有兩種類似的方法在Java的ObjectInputStream:什麼時候會使用ObjectInputStream.readUshared()與.readObject()?

readUnshared()

readObject()

的文檔狀態:

public Object readUnshared() throws IOException, ClassNotFoundException

從ObjectInputStream中讀取「未共享」對象。此方法與readObject相同,只是它阻止對readObject的後續調用,並且readUnshared不會返回通過此調用獲取的反序列化實例的其他引用。具體來說:

如果調用readUnshared以反序列化後向引用(先前已寫入流的對象的流表示形式),則會拋出ObjectStreamException。

如果readUnshared返回成功,則任何後續嘗試反序列化對由readUnshared反序列化的流句柄的反向引用都將導致拋出ObjectStreamException。

通過讀取反序列化對象未共享使與返回對象關聯的流處理無效。請注意,這本身並不總是保證readUnshared返回的引用是唯一的;反序列化的對象可以定義一個readResolve方法,該方法返回一個可見的對象給另一方,或者readUnshared可以返回一個Class對象或者可以在流中其他地方或者通過外部手段獲得的枚舉常量。如果反序列化的對象定義了一個readResolve方法,並且該方法的調用返回一個數組,則readUnshared會返回該數組的淺表副本;這保證了返回的數組對象是唯一的,即使基礎數據流已被操作,也無法從ObjectObject的readObject或readUnshared調用中獲得第二次。

重寫此方法的ObjectInputStream子類只能在擁有「enableSubclassImplementation」SerializablePermission;任何嘗試實例化沒有此權限的子類都將導致拋出SecurityException。

但我想知道如果任何人有現實生活中使用這種利用.readUnshared() VS .readObject()

+0

從未使用它。一種用法是作爲協議完整性檢查來確保發送者正在使用'writeUnshared()'。如果他不是所描述的例外情況將會導致。 – EJP 2015-04-03 02:51:41

回答

0

我認爲可能是與安全有關的非常特殊的情況(?)。像這樣(從here)。

A.6護非共享反序列化對象

如果一個類的任何私有或包專用對象引用字段, 和類依賴於以下事實:這些對象引用不可用的類之外​​ (或包),那麼引用的 對象必須作爲反序列化 進程的一部分進行防禦性複製,否則ObjectOutputStream.writeUnshared和ObjectInputStream.readUnshared方法(引入到版本1中。應使用JavaTM 2 SDK標準版的 中的4個)來確保對內部對象的唯一引用 。

在複製方法中,從流 應被視爲「不可信的輸入」反序列化子對象:新創建的對象, 初始化爲具有相同的值作爲反序列化子對象, 應該被替換爲通過readObject方法獲得子對象。 例如,假定對象具有一個專用字節數組字段,B,即 必須保持私有:

private void readObject(ObjectInputStream s) 
    throws IOException, ClassNotFoundException 
{ 
    s.defaultReadObject(); 

    b = (byte[])b.clone(); 

    if (<invariants are not satisfied>) 
     throw new java.io.StreamCorruptedException(); 
} 

考慮包含於 內部(一定私有)的引用 不變對象的串行化時,此問題是特別重要的可變的子對象。如果在對容器對象的反序列化過程中沒有采取特殊措施複製子對象 ,則對序列化流進行寫入訪問的惡意方可能通過僞造對其可變子對象的引用來違反容器對象的不可變性,以及使用這些 引用來更改容器對象的內部狀態。因此,在這個 的情況下,不可變容器類提供一個 特定於類的反序列化方法是至關重要的,該方法使得它反序列化每個可變組件對象的私有副本 。請注意,對於保持不變性的目的,無需複製 不可變的組件對象。

重要的是要注意調用克隆可能並不總是 防禦複製子對象的正確方法。如果克隆方法不能指望生成獨立副本(而不是「盜取」副本的參考號),則應使用其他方法生成副本 。如果子對象的類不是最終的,則應始終使用備選的複製方法,因爲它調用的克隆方法或幫助器方法可能會被子類覆蓋。

中的JavaTM 2 SDK,標準版,獨特的 引用反序列化對象的1.4版本開始也可以通過使用 ObjectOutputStream.writeUnshared保證和ObjectInputStream.readUnshared 方法,從而避免了併發症,性能成本和內存 防禦性複製的開銷。