Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does serialization preserve object identity?

Tags:

I am using the Java Serializable interface and the ObjectOutputStream to serialize objects (until now, this method has been sufficient for my purposes).

My API relies on object identity for some operations and I’m wondering if it will be preserved by serialization. That is to say: if, for two arbitrary objects a and b, it holds a == b before serialization, does it still hold after deserialization?

I’ve found some texts that claim the contrary – but they either wrote about an older version of the JRE (I’m only interested in 1.6 and perhaps 1.5), or were concerned with RMI (which is not relevant for me).

The documentation isn’t very forthcoming regarding object identity. A technical article on sun.com mentions that ObjectOutputStream uses caching on objects, which to me only makes sense if the object identity is indeed preserved but I’m not confident enough to rely on this flimsy evidence.

I’ve tried it out (Java 1.6, OS X) and found that yes, the identity of objects remains unchanged by serialization. But can I extrapolate from these results or are they unreliable?

For my test, I’ve serialized the following object graph:

C----------+ | b1    b2 | +----------+   |      |   v      v B---+  B---+ | a |  | a | +---+  +---+    \    /     \  /      \/    A----+    |    |    +----+ 

A minimal reproducing code:

import java.io.*;  public class SerializeTest {     static class A implements Serializable {}      static class B implements Serializable {         final A a;          public B(A a) {             this.a = a;         }     }      static class C implements Serializable {         final B b1, b2;          public C() {             A object = new A();             b1 = b2 = new B(object);         }     }      public static void main(String[] args) throws IOException,             ClassNotFoundException {         C before = new C();         System.out.print("Before: ");         System.out.println(before.b1.a == before.b2.a);          // Serialization.         ByteArrayOutputStream data = new ByteArrayOutputStream();         ObjectOutputStream out = new ObjectOutputStream(data);         out.writeObject(before);         out.close();          // Deserialization.         ObjectInputStream in =             new ObjectInputStream(new ByteArrayInputStream(data.toByteArray()));         C after = (C) in.readObject();         System.out.print("After: ");         System.out.println(after.b1.a == after.b2.a);     } } 
like image 801
Konrad Rudolph Avatar asked Aug 29 '09 15:08

Konrad Rudolph


People also ask

What is purpose of serialization of an object?

Serialization in Java allows us to convert an Object to stream that we can send over the network or save it as file or store in DB for later usage. Deserialization is the process of converting Object stream to actual Java Object to be used in our program.

What happens when you serialize an object?

Serialization is the process of converting an object into a stream of bytes to store the object or transmit it to memory, a database, or a file. Its main purpose is to save the state of an object in order to be able to recreate it when needed. The reverse process is called deserialization.

What are the disadvantages of serialization?

Since serialization does not offer any transaction control mechanisms per se, it is not suitable for use within applications needing concurrent access without making use of additional APIs.

What happens when object is serialization in Java?

To serialize an object means to convert its state to a byte stream so that the byte stream can be reverted back into a copy of the object. A Java object is serializable if its class or any of its superclasses implements either the java.


2 Answers

For two arbitrary objects a and b, if it holds a == b before serialization, it will still hold true after deserialization IF:

  1. Both a and b are written as and subsequently read from as parts of the same stream. Here's a quote from ObjectInputStream documentation: "Graphs of objects are restored correctly using a reference sharing mechanism."
  2. Class of a and b does not override readResolve() that has the potential of changing how references are restored back; neither do classes that hold a and b.

For all other cases, object identity will NOT be preserved.

like image 193
ChssPly76 Avatar answered Sep 28 '22 04:09

ChssPly76


The answer is no, by default object identity is not preserved via serialization if you are considering 2 separate serializations of a given object/graph. For example, if a I serialize an object over the wire (perhaps I send it from a client to a server via RMI), and then do it again (in separate RMI calls), then the 2 deserialized objects on the server will not be ==.

However, in a "single serialization" e.g. a single client-server message which is a graph containing the same object multiple times then upon deserialization, identity is preserved.

For the first case, you can, however, provide an implementation of the readResolve method in order to ensure that the correct instance is returned (e.g. in the typesafe enum pattern). readResolve is a private method which will be called by the JVM on a de-serialized Java object, giving the object the chance to return a different instance. For example, this is how the TimeUnit enum may have been implemented before enum's were added to the language:

public class TimeUnit extends Serializable {      private int id;     public TimeUnit(int i) { id = i; }     public static TimeUnit SECONDS = new TimeUnit(0);      //Implement method and return the relevant static Instance     private Object readResolve() throws ObjectStreamException {         if (id == 0) return SECONDS;         else return this;     } } 

.

like image 39
oxbow_lakes Avatar answered Sep 28 '22 04:09

oxbow_lakes