Class CloseableTracker

java.lang.Object
io.permazen.util.CloseableTracker
All Implemented Interfaces:
Closeable, AutoCloseable

public class CloseableTracker extends Object implements Closeable
Keeps track of Closeable objects (termed items) that must be reliably closed prior to shutting down some associated context, but that also must not be closed prior to becoming unreachable, when the straightforward strategy of just storing them until context shutdown would require too much memory. In a typical scenario, these items are returned (indirectly by reference from some associated holder object) from some method to callers who cannot be expected to reliably close them. Following the simple strategy of just storing all unclosed items until context shutdown means unbounded memory use can occur; this class solves that problem.

For a concrete example, consider a method that returns an Iterator, where the returned iterator is implemented based on some Closeable internal resource. Since Iterator has no close() method, the caller of the method cannot be expected to "close" the Iterator (and in turn, the internal resource), when done with it. Such a method could use add(iterator, resource) to close this leak.

For each such context, an instance of this class may be used to register and track the associated items, guaranteeing that they will always eventually be closed, but doing so in a way that avoids memory leaks: For each item, there must be a corresponding holder object containing a reference to it. The holder objects are then tracked by this class using weak references. When a holder object is no longer strongly referenced, the corresponding item is closed. With this scheme, no memory leak occurs due to this tracking, even when arbitrarily many items are created. This of course assumes that when a holder object is no longer referenced, the associated item may be safely closed.

A registered Closeable item is closed at the first occurrence of any of the following:

  • The application itself invokes Closeable.close() on the item
  • The associated holder object is no longer strongly referenced, and then poll() is invoked
  • close() is invoked
  • finalize() is invoked (i.e., this instance is garbage collected)

Note that Closeable.close() is required to be idempotent, so application usage that results in eager closing of items is appropriate and encouraged. Use of this class may occasionally result in Closeable.close() being invoked more than once for registered items.

Instances of this class are thread safe.

  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    protected final Logger
     
  • Constructor Summary

    Constructors
    Constructor
    Description
    Constructor.
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    add(Object holder, Closeable item)
    Add an item to the set of items being tracked by this instance.
    void
    Close all unclosed items associated with this instance.
    protected void
    Handle an exception thrown while attempting to close() and item.
    protected void
     
    void
    Poll the internal weak reference queue and close any unclosed items whose holders are no longer reachable.
    void
    Reset this instance.

    Methods inherited from class java.lang.Object

    clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • log

      protected final Logger log
  • Constructor Details

    • CloseableTracker

      public CloseableTracker()
      Constructor.
  • Method Details

    • add

      public void add(Object holder, Closeable item)
      Add an item to the set of items being tracked by this instance.

      If the holder becomes no longer reachable, the item will (eventually) be closed.

      Parameters:
      holder - item's holder
      item - item to track
      Throws:
      IllegalArgumentException - if either parameter is null
    • poll

      public void poll()
      Poll the internal weak reference queue and close any unclosed items whose holders are no longer reachable.

      Applications should invoke this method periodically to avoid memory leaks.

    • close

      public void close()
      Close all unclosed items associated with this instance.

      The implementation in CloseableTracker just invokes reset().

      Specified by:
      close in interface AutoCloseable
      Specified by:
      close in interface Closeable
    • reset

      public void reset()
      Reset this instance.

      Results in the forced closing of all unclosed items associated with this instance.

      This instance may be reused after invoking this method.

    • exceptionDuringClose

      protected void exceptionDuringClose(Closeable item, Throwable e)
      Handle an exception thrown while attempting to close() and item.

      The implementation in CloseableTracker just logs the exception at debug level and returns.

      Parameters:
      item - item that was closed
      e - exeption thrown
    • finalize

      protected void finalize() throws Throwable
      Overrides:
      finalize in class Object
      Throws:
      Throwable