Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Java - ObjectInputStream readUnshared() method



Description

The Java ObjectInputStream readUnshared() method 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.

Declaration

Following is the declaration for java.io.ObjectInputStream.readUnshared() method.

public Object readUnshared()

Parameters

NA

Return Value

This method returns a reference to deserialized object.

Exception

  • ClassNotFoundException − If class of an object to deserialize cannot be found.

  • StreamCorruptedException − If control information in the stream is inconsistent.

  • ObjectStreamException − If object to deserialize has already appeared in stream.

  • OptionalDataException − If primitive data is next in stream.

  • IOException − If an I/O error occurs during deserialization.

Example - Usage of ObjectInputStream readUnshared() method

The following example shows the usage of Java ObjectInputStream readUnshared() method.

ObjectInputStreamDemo.java

package com.tutorialspoint;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class ObjectInputStreamDemo {
   public static void main(String[] args) {
      String s = "Hello World";
      
      try {
         // create a new file with an ObjectOutputStream
         FileOutputStream out = new FileOutputStream("test.txt");
         ObjectOutputStream oout = new ObjectOutputStream(out);

         // write something in the file
         oout.writeUnshared(s);
         oout.flush();

         // create an ObjectInputStream for the file we created before
         ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test.txt"));

         // read and print the unshared object
         System.out.println("" + ois.readUnshared());
      } catch (Exception ex) {
         ex.printStackTrace();
      }
   }
}

Output

Let us compile and run the above program, this will produce the following result−

Hello World

Example - Avoiding Shared References

The following example shows the usage of Java ObjectInputStream readUnshared() method. This example demonstrates how readUnshared() prevents objects from being shared when deserializing multiple references to the same object.

ObjectInputStreamDemo.java

package com.tutorialspoint;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class ObjectInputStreamDemo {
   public static void main(String[] args) {
      String filename = "personData.ser";

      // Writing the same object twice to a file
      try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename))) {
         Person person = new Person("Alice");
         oos.writeObject(person);
         oos.writeObject(person); // Writing the same object again
         System.out.println("Same object written twice.");
      } catch (IOException e) {
         e.printStackTrace();
      }

      // Reading objects using readUnshared()
      try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename))) {
         Person p1 = (Person) ois.readUnshared();
         Person p2 = (Person) ois.readUnshared();

         System.out.println("Objects read successfully.");
         System.out.println("Are they the same instance? " + (p1 == p2)); // Should be false
      } catch (IOException | ClassNotFoundException e) {
         e.printStackTrace();
      }
   }

   static class Person implements Serializable {
      private static final long serialVersionUID = 1L;
      String name;

      public Person(String name) {
         this.name = name;
      }

      public void display() {
         System.out.println("Person Name: " + name);
      }
   }
}

Output

Let us compile and run the above program, this will produce the following result−

Same object written twice.
java.io.InvalidObjectException: cannot read back reference as unshared
	at java.base/java.io.ObjectInputStream.readHandle(ObjectInputStream.java:1876)
	at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1727)
	at java.base/java.io.ObjectInputStream.readUnshared(ObjectInputStream.java:635)
	at ReadUnsharedExample1.main(ConsoleWriter.java:32)

Explanation

  • A Person object is written twice to the file.

  • When using readUnshared(), each read operation returns a new instance of the object.

  • The comparison p1 == p2 returns false, proving that readUnshared() prevents object sharing.

Example - Avoiding Reference Sharing in Collections

The following example shows the usage of Java ObjectInputStream readUnshared() method. This example demonstrates how readUnshared() prevents reference sharing when deserializing collections containing the same object multiple times.

ObjectInputStreamDemo.java

package com.tutorialspoint;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class ObjectInputStreamDemo {
   public static void main(String[] args) {
      String filename = "cars.ser";

      // Creating a list of cars with duplicate references
      List<Car> cars = new ArrayList<>();
      Car car1 = new Car("Toyota");
      cars.add(car1);
      cars.add(car1); // Adding the same object reference again

      // Writing the list to a file
      try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filename))) {
         oos.writeObject(cars);
         System.out.println("Car list written with duplicate references.");
      } catch (IOException e) {
         e.printStackTrace();
      }

      // Reading the list and using readUnshared() to avoid reference sharing
      try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename))) {
         List<Car> readCars = (List<Car>) ois.readObject();
         Car carA = (Car)readCars.get(0); // Read first Car
         Car carB = (Car) readCars.get(0); // Read second Car (should be a new instance)
         System.out.println("Before modifying:");
         carA.display();
         carB.display();

         // Modifying one instance
         carA.setModel("Honda");

         System.out.println("After modifying carA:");
         carA.display();
         carB.display(); // carB should remain "Toyota"
      } catch (IOException | ClassNotFoundException e) {
         e.printStackTrace();
      }
   }
   static class Car implements Serializable {
      private static final long serialVersionUID = 1L;
      String model;

      public Car(String model) {
         this.model = model;
      }

      public void setModel(String model) {
         this.model = model;
      }

      public void display() {
         System.out.println("Car Model: " + model);
      }
   }
}

Output

Let us compile and run the above program, this will produce the following result−

Car list written with duplicate references.
Before modifying:
Car Model: Toyota
After modifying carA:
Car Model: Honda

Explanation

  • A List<Car> contains two references to the same Car object.

  • The list is serialized and written to a file.

  • When reading back The entire list is deserialized normally. readUnshared() is used to read the two cars separately, ensuring they are distinct objects.

  • When modifying carA, carB remains unchanged, proving they are separate instances.

java_io_objectinputstream.htm
Advertisements