简体   繁体   中英

Sending the same objects with different fields over an object serialized stream

I have a client/server program, and I'm sending objects through ObjectOutputStream via writeObject() and readObject() .

The object I'm sending is class consisting of a couple of fields, and another object inside (let's call the outer object Wrapper and the inner Inner . Both the custom objects implement serializable .

The first time I send the Wrapper over, everything works flawlessly. Everything stored in both Wrapper , Inner and all the fields serialize and deserialize without problems.

However, when the client then modifies the Inner class, puts it in the Wrapper , and sends it one more time, the Inner instance received by the server, is identical to the one received the first time around.

My client:

Inner inner = new Inner();
inner.setValue("value");

ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
out.writeObject(new Wrapper(inner));

Server:

ObjectInputStream in = new ObjectInputStream(clientSocket.getInputStream());
Wrapper wrapper = (Wrapper) in.readObject();
String value = wrapper.getInner().getValue();

Client then modifies the Inner class (same instance as before) with a DIFFERENT string (ie. containing other letters then the first one):

inner.setValue("newValue");
out.writeObject(new Wrapper(inner));

However, when I look at the inner.getValue() on the server, it has not changed and is still equal to "value" .

I solved this, by making a hard copy of the inner class, before sending it over:

Inner newInner = new Inner();
newInner.setValue("newValue");
out.writeObject(new Wrapper(newInner));

The new value now is updated as it should.

Why does serialization work this way?

This is the expected behavior of the ObjectOutputStream . To quote from the Javadocs:

Multiple references to a single object are encoded using a reference sharing mechanism so that graphs of objects can be restored to the same shape as when the original was written.

Since you are using the same inner class reference, it just sends over a reference to the previously sent object. It does not check all of the fields of all of the objects to see if any of them have changed. I suspect that not only was inner.getValue() equal to the first object sent but that the inner object received by the server in the 2nd object was the same object ( == ) as the inner from the first object.

If you had called:

out.reset();

before the sending of the object with the adjusted inner field, your code should work. The reset() method clears the reference cache which helps the serialization stream be efficient. As a side note, reset() is especially necessary if you are sending a large number of temporary objects across a stream because otherwise these objects are cached in memory and can cause heap exhaustion.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM