Sending the Same But Modifed Object Over Objectoutputstream

Sending the same but modifed object over ObjectOutputStream

The stream has a reference graph, so an object which is sent twice will not give two objects on the other end, you will only get one. And sending the same object twice separately will give you the same instance twice (each with the same data - which is what you're seeing).

See the reset() method if you want to reset the graph.

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

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.

ObjectOutputStream writes same instances differently depending on how i open stream

Java serialization, implemented by Object{Output,Input}Stream, in addition to metadata and data for each object, has a stream header that only occurs once and not for each object. Normally in a file this amounts to a file header. If you want to put multiple streams in one file, you must manage the stream boundaries yourself:

//nopackage
import java.io.*;

public class SO71319428MultipleSerial {
public static void main (String[] args) throws Exception {
User[] a = { new User("Alice",1), new User("Bob",2), new User("Carol",3) };
for( User u : a )
try( ObjectOutputStream oo = new ObjectOutputStream(new FileOutputStream(filename,true)) ){
oo.writeObject(u);
}
System.out.println("reading "+new File(filename).length());
try( InputStream fi = new FileInputStream(filename) ){
for( int i = 0; i < 3; i++ ){
ObjectInputStream oi = new ObjectInputStream(fi);
System.out.println( oi.readObject() );
// DON'T close because that closes the underlying FileInputStream; just leak instead
}
}
}
public static String filename = "SO71319428.out";

static class User implements Serializable {
String name; int id;
public User(String name, int id){ this.name=name; this.id=id; }
public String toString(){ return name+" is #"+id; }
}
}
->
reading 283
Alice is #1
Bob is #2
Carol is #3

This is less flexible than the single-stream (with multiple objects) approach, because that allows you to write any sequence of objects whose types and end can be recognized when reading without any help; with the multiple-stream approach your code must be able to determine when a stream ends and needs to be restarted.

Having to recreate ObjectOutputStream every time

When you send data on an object stream, it will send each object only once. This means if you modify and object and send it multiple times, you need to either use writeUnshared(mutableObject) or reset() which clears the cache of objects already sent.


You can't create an ObjectOutput/InputStream repeatly. If you want to make sure data is sent instead of buffered use flush(). If you are sending data like int instead of Objects, try DataOutput/InputStream.



Related Topics



Leave a reply



Submit