Search code examples
javaioresetflush

Difference Between flush() vs reset() in JAVA


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++;
}

Solution

  • 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]