orc.trace.handles
Class HandleOutputStream

java.lang.Object
  extended by java.io.OutputStream
      extended by java.io.ObjectOutputStream
          extended by orc.trace.handles.HandleOutputStream
All Implemented Interfaces:
java.io.Closeable, java.io.DataOutput, java.io.Flushable, java.io.ObjectOutput, java.io.ObjectStreamConstants

public final class HandleOutputStream
extends java.io.ObjectOutputStream

Used in conjunction with Handle to explicitly manage the lifetime of serialized references. Use it like this:

  1. Instead of using pointers in your object graph, use instances of Handle.
  2. You should call ObjectOutputStream.reset() regularly to keep the output stream from wasting memory.
  3. Handles are not affected by ObjectOutputStream.reset(); instead, the order in which Handles are constructed and serialized determines when the output stream forgets about them.

Some background on the problem this solves: the standard ObjectOutputStream uses a cache of every object it has seen in order to serialize pointers. This prevents the objects from being GCed. You can clear the cache with a call to ObjectOutputStream.reset(), but then pointers will no longer be correct.

Why doesn't ObjectOutputStream just use a weak hash map? That would be fine for writing, but it wouldn't work for reading. Reading still needs to cache pointer values to reconstruct the object graph, but it can't tell when it has seen the last reference to an object in the input file.

The solution implemented here is to allow pointers to be reset on an individual basis, so that both the output and input streams can tell when they have seen the last pointer to an object and clear the object from their caches.

Author:
quark
See Also:
HandleOutputStream, Handle

Nested Class Summary
 
Nested classes/interfaces inherited from class java.io.ObjectOutputStream
java.io.ObjectOutputStream.PutField
 
Field Summary
 
Fields inherited from interface java.io.ObjectStreamConstants
baseWireHandle, PROTOCOL_VERSION_1, PROTOCOL_VERSION_2, SC_BLOCK_DATA, SC_ENUM, SC_EXTERNALIZABLE, SC_SERIALIZABLE, SC_WRITE_METHOD, STREAM_MAGIC, STREAM_VERSION, SUBCLASS_IMPLEMENTATION_PERMISSION, SUBSTITUTION_PERMISSION, TC_ARRAY, TC_BASE, TC_BLOCKDATA, TC_BLOCKDATALONG, TC_CLASS, TC_CLASSDESC, TC_ENDBLOCKDATA, TC_ENUM, TC_EXCEPTION, TC_LONGSTRING, TC_MAX, TC_NULL, TC_OBJECT, TC_PROXYCLASSDESC, TC_REFERENCE, TC_RESET, TC_STRING
 
Constructor Summary
HandleOutputStream(java.io.OutputStream out)
           
HandleOutputStream(java.io.OutputStream out, int resetInterval)
          The reset interval determines how often maybeReset() actually resets.
 
Method Summary
 void freeHandle(java.lang.Object value)
          Free the handle ID associated with the given value.
 int getHandle(java.lang.Object value)
          Return the handle ID associated with a handle value.
 void maybeReset()
          This uses the reset interval set by setResetInterval(int) or HandleOutputStream(OutputStream, int) to decide whether to reset the output stream.
 int newHandle(java.lang.Object value)
          Create and return a new handle ID for the given value.
 void setResetInterval(int resetInterval)
          Change the reset interval.
 
Methods inherited from class java.io.ObjectOutputStream
annotateClass, annotateProxyClass, close, defaultWriteObject, drain, enableReplaceObject, flush, putFields, replaceObject, reset, useProtocolVersion, write, write, write, writeBoolean, writeByte, writeBytes, writeChar, writeChars, writeClassDescriptor, writeDouble, writeFields, writeFloat, writeInt, writeLong, writeObject, writeObjectOverride, writeShort, writeStreamHeader, writeUnshared, writeUTF
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

HandleOutputStream

public HandleOutputStream(java.io.OutputStream out)
                   throws java.io.IOException
Throws:
java.io.IOException

HandleOutputStream

public HandleOutputStream(java.io.OutputStream out,
                          int resetInterval)
                   throws java.io.IOException
The reset interval determines how often maybeReset() actually resets.

Throws:
java.io.IOException
Method Detail

setResetInterval

public void setResetInterval(int resetInterval)
Change the reset interval. Also resets the current counter so the next reset occurs after resetInterval calls to maybeReset().


maybeReset

public void maybeReset()
                throws java.io.IOException
This uses the reset interval set by setResetInterval(int) or HandleOutputStream(OutputStream, int) to decide whether to reset the output stream. The default (safe) behavior is to always reset.

Throws:
java.io.IOException

getHandle

public int getHandle(java.lang.Object value)
Return the handle ID associated with a handle value.


newHandle

public int newHandle(java.lang.Object value)
              throws java.io.IOException
Create and return a new handle ID for the given value.

Throws:
java.io.IOException

freeHandle

public void freeHandle(java.lang.Object value)
Free the handle ID associated with the given value. Only call this if you know the handle exists.