When would one use ObjectInputStream.readUnshared() vs .readObject()?
Asked Answered
P

2

6

There are two similar methods in the Java ObjectInputStream:

readUnshared()

and

readObject()

The documentation states:

public Object readUnshared() throws IOException, ClassNotFoundException

Reads an "unshared" object from the ObjectInputStream. This method is identical to readObject, except that it prevents subsequent calls to readObject and readUnshared from returning additional references to the deserialized instance obtained via this call. Specifically:

If readUnshared is called to deserialize a back-reference (the stream representation of an object which has been written previously to the stream), an ObjectStreamException will be thrown.

If readUnshared returns successfully, then any subsequent attempts to deserialize back-references to the stream handle deserialized by readUnshared will cause an ObjectStreamException to be thrown.

Deserializing an object via readUnshared invalidates the stream handle associated with the returned object. Note that this in itself does not always guarantee that the reference returned by readUnshared is unique; the deserialized object may define a readResolve method which returns an object visible to other parties, or readUnshared may return a Class object or enum constant obtainable elsewhere in the stream or through external means. If the deserialized object defines a readResolve method and the invocation of that method returns an array, then readUnshared returns a shallow clone of that array; this guarantees that the returned array object is unique and cannot be obtained a second time from an invocation of readObject or readUnshared on the ObjectInputStream, even if the underlying data stream has been manipulated.

ObjectInputStream subclasses which override this method can only be constructed in security contexts possessing the "enableSubclassImplementation" SerializablePermission; any attempt to instantiate such a subclass without this permission will cause a SecurityException to be thrown.

But I was wondering if anyone had real life uses for this using .readUnshared() vs .readObject()

Platinum answered 2/4, 2015 at 23:59 Comment(1)
Never used it. One use would be as a protocol sanity check to ensure the sender was using writeUnshared(). If he isn't the exception described will result.Perspicacity
D
2

I believe it could be very special cases related to security(?). Like this one (from here).

A.6 Guarding Unshared Deserialized Objects

If a class has any private or package private object reference fields, and the class depends on the fact that these object references are not available outside the class (or package), then either the referenced objects must be defensively copied as part of the deserialization process, or else the ObjectOutputStream.writeUnshared and ObjectInputStream.readUnshared methods (introduced in version 1.4 of the JavaTM 2 SDK, Standard Edition) should be used to ensure unique references to the internal objects.

In the copying approach, the sub-objects deserialized from the stream should be treated as "untrusted input": newly created objects, initialized to have the same value as the deserialized sub-objects, should be substituted for the sub-objects by the readObject method. For example, suppose an object has a private byte array field, b, that must remain private:

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

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

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

This issue is particularly important when considering serialization of immutable objects containing internal (necessarily private) references to mutable sub-objects. If no special measures are taken to copy the sub-objects during deserialization of the container object, then a malicious party with write access to the serialization stream may violate the container object's immutability by forging references to its mutable sub-objects, and using these references to change the internal state of the container object. Thus, in this case it is imperative that the immutable container class provide a class-specific deserialization method which makes private copies of each mutable component object it deserializes. Note that for the purpose of maintaining immutability, it is unnecessary to copy immutable component objects.

It is also important to note that calling clone may not always be the right way to defensively copy a sub-object. If the clone method cannot be counted on to produce an independent copy (and not to "steal" a reference to the copy), an alternative means should be used to produce the copy. An alternative means of copying should always be used if the class of the sub-object is not final, since the clone method or helper methods that it calls may be overridden by subclasses.

Starting in version 1.4 of the JavaTM 2 SDK, Standard Edition, unique references to deserialized objects can also be ensured by using the ObjectOutputStream.writeUnshared and ObjectInputStream.readUnshared methods, thus avoiding the complication, performance costs and memory overhead of defensive copying.

Devote answered 31/7, 2015 at 12:14 Comment(0)
E
0

I have used readUnshared() successfully when readObject() produces OutOfMemory exception. More info: https://orenkishon.wordpress.com/2014/06/28/java-memory-leak-caused-by-objectinputstream/

Ethbinium answered 22/12, 2022 at 13:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.