5 Replies Latest reply: Dec 14, 2009 3:12 AM by 843790 RSS

    writeUnshared() vs reset()

    843790
      Hi,
      if I skip reset() in the code bellow, OutOfMemoryError occurs after a certain period of time. Is it a feature or is it a bug of ObjectOutputStream? I checked it with debugger and I see a lots of null objects gathering at oos.handles.objs array.
      public class A implements Serializable {
           
           static A a = new A();
           
           //long i;
           
           public static void main(String[] args) throws Exception {
                ObjectOutputStream oos = new ObjectOutputStream(
                     new ByteArrayOutputStream() {
                          @Override public void write(byte[] b, int off, int len) { }
                     }
                );
                long ctr = 0l;
                while(ctr++<100000000l) {
                     a = new A();
                     
                     oos.writeUnshared(a); //Heap space when reset is skipped
                     oos.reset();
                     
                     if(ctr%1000==0) {
                          System.out.println(Runtime.getRuntime().freeMemory());
                     }
                }
                oos.close();
           }
        • 1. Re: writeUnshared() vs reset()
          jtahlborn
          unfortunately, if you want to keep an objectoutputstream open for an extended period of time, you must periodically call reset. using writeUnshared is not sufficient. it's probably somewhere between a feature and a bug, but it's been there for a long time and has not changed.
          • 2. Re: writeUnshared() vs reset()
            EJP
            It's not a bug. Read the Javadoc. They aren't functionally equivalent. writeUnshared() inhibits remembering the actual object argument supplied, but not the objects reachable from it. +'Note that the rules described above only apply to the base-level object written with writeUnshared, and not to any transitively referenced sub-objects in the object graph to be serialized.'+ reset() clears the entire object memory of the stream. If you're using reset() there is no need to use writeUnshared() rather than writeObject().
            • 3. Re: writeUnshared() vs reset()
              jtahlborn
              ejp wrote:
              It's not a bug. Read the Javadoc. They aren't functionally equivalent. writeUnshared() inhibits remembering the actual object argument supplied, but not the objects reachable from it. +'Note that the rules described above only apply to the base-level object written with writeUnshared, and not to any transitively referenced sub-objects in the object graph to be serialized.'+
              wow, that's an interesting nuance that i never noticed before. that seems kind of... odd. that seems like sort of an odd distinction to make. if i want to write a new instance of an object, wouldn't i most likely want a new instance of any nested objects? i guess it could go either way...
              If you're using reset() there is no need to use writeUnshared() rather than writeObject().
              not entirely true. for instance, if you were reusing a list between each call (repopulating the list with new elements), you would not get the expected behavior by using writeObject(). well, i guess if you were calling reset() after every call to writeObject() it would work fine. the way i've done it previously is using writeUnshared with periodic calls to reset() (like every 100 objects or so).

              Edited by: jtahlborn on Dec 11, 2009 11:09 PM
              • 4. Re: writeUnshared() vs reset()
                EJP
                If you're using reset() there is no need to use writeUnshared() rather than writeObject().
                not entirely true.
                Entirely true.
                for instance, if you were reusing a list between each call (repopulating the list with new elements), you would not get the expected behavior by using writeObject().
                Yes you would, if you were calling reset().
                well, i guess if you were calling reset() after every call to writeObject() it would work fine.
                Which is what I said.
                • 5. Re: writeUnshared() vs reset()
                  843790
                  I can't fully agree with you because of the followings:

                  -As you can see in my code above, I serialize totally isolated objects, no further references in class "A". At least this is the intent... More particularly in my original code which implied this question, I serialize the state of flyweight objects many times, which are POJOs and have only primitive fields. That's okay to use writeObject() and reset() regularly after it, but I simply don't need that round from ObjectOutputStream to register and throw the object reference million times.

                  -The other thing: writeUnshared(), manifestly, puts a null reference into a collection (ObjectOutputStream$HandleTable, objs array) without any sense every time it's invoked. As I see, this collection grows and causes the StackOverflowException. I hardly can accept it as a feature.