5

I was just wondering what the difference between flush and reset is? Why is it using reset after flush in example? Why is reset method used if memory cache is wiped by flush method?

ObjectOutputStream oos = new ObjectOutputStream(bos);

while(true){
    oos.writeObject(object);
    oos.flush();
    oos.reset();

    object.x++;
}
Efe Zeybek
  • 83
  • 1
  • 2
  • 14

3 Answers3

6

Why is reset method used if memory cache is wiped by flush method?

flush() will write the buffer of the ObjectOutputStream object in the underlying OutputStream but it will not reset the whole state of the ObjectOutputStream object.

If you open the ObjectOutputStream source code class, you can see that beyond the buffer it contains many instance fields.
Here is a little snippet :

/** filter stream for handling block data conversion */
private final BlockDataOutputStream bout;
/** obj -> wire handle map */
private final HandleTable handles;
/** obj -> replacement obj map */
private final ReplaceTable subs;
/** recursion depth */
private int depth;
/** buffer for writing primitive field values */
private byte[] primVals;

Some handle the conversion, others handle the cache, and so for... ObjectOutputStream.reset() will have effects on this state :

Reset will disregard the state of any objects already written to the stream.

and

Objects previously written to the stream will not be referred to as already being in the stream. They will be written to the stream again.

These detail matter as ObjectOutputStream uses a reference sharing mechanism.
So writing in the stream multiple times the same object but with a different state will write the object with the original state multiple times.
The top level documentation of ObjectOutputStream explains that and more (emphasis is mine) :

The default serialization mechanism for an object writes the class of the object, the class signature, and the values of all non-transient and non-static fields. References to other objects (except in transient or static fields) cause those objects to be written also. 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.

You should now understand the reset() meaning.


Example illustrating a cache issue with ObjectOutputStream:

Execute this class that write 10 times the same object but with a different state i nan ObjectOutputStream without invoking reset() between the writings :

public class FlushAndReset {

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);

        Foo foo = new Foo();
        for (int i = 0; i < 10; i++) {
            foo.setValue(i);
            oos.writeObject(foo);
            oos.flush();
            // oos.reset();
        }

        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
        for (int i = 0; i < 10; i++) {
            Object obj = ois.readObject();
            System.out.println(obj);
        }
    }
}

With Foo defined as :

public class Foo implements Serializable {

    private int value;

    public void setValue(int value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "Foo [value=" + value + "]";
    }

}

As you will read the content of the BOS you will get :

Foo [value=0]

Foo [value=0]

Foo [value=0]

Foo [value=0]

Foo [value=0]

Foo [value=0]

Foo [value=0]

Foo [value=0]

Foo [value=0]

Foo [value=0]

Uncomment the reset() and you should see the change :

Foo [value=0]

Foo [value=1]

Foo [value=2]

Foo [value=3]

Foo [value=4]

Foo [value=5]

Foo [value=6]

Foo [value=7]

Foo [value=8]

Foo [value=9]

davidxxx
  • 125,838
  • 23
  • 214
  • 215
2

The reset() will disregard the state of any objects already written to the stream. The state is reset to be the same as a new ObjectOutputStream. The current point in the stream is marked as reset so the corresponding ObjectInputStream will be reset at the same point. Objects previously written to the stream will not be refered to as already being in the stream. They will be written to the stream again.

The flush() method flushes the stream. This will write any buffered output bytes and flush through to the underlying stream.

The flush() method will do clear the buffer and write to the stream while reset() will be used to change the objects which were already written to the stream.

Gaurav Srivastav
  • 2,381
  • 1
  • 15
  • 18
0

reset() will invalidate all objects that have been sent. If you are sending unchanged objects again only a reference is transmitted allowing to reuse the cached version of the already transmitted object. This is much more efficient than always sending the entire object.

In your example the value of objects's member x is increased, thus the object changes. If you need to send the changed values it is necesarry to call reset() first so that the object is actually rewritten to the stream.

On the other hand flush() will only make sure that data is actually written to the stream. The write operation will only put data to the buffer and may write it to the stream depending on the buffer size. Calling flush() will guarantee that the data is written to the stream. But flush will not clear the cached objects.

JannisW
  • 195
  • 7