public class CloseableTracker extends Object implements Closeable
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:
Closeable.close()
on the itempoll()
is invokedclose()
is invokedfinalize()
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.
Constructor and Description |
---|
CloseableTracker()
Constructor.
|
Modifier and Type | Method and Description |
---|---|
void |
add(Object holder,
Closeable item)
Add an item to the set of items being tracked by this instance.
|
void |
close()
Close all unclosed items associated with this instance.
|
protected void |
exceptionDuringClose(Closeable item,
Throwable e)
Handle an exception thrown while attempting to
close() and item. |
protected void |
finalize() |
void |
poll()
Poll the internal weak reference queue and close any unclosed items whose holders are no longer reachable.
|
void |
reset()
Reset this instance.
|
protected final Logger log
public void add(Object holder, Closeable item)
If the holder
becomes no longer reachable, the item
will (eventually) be closed.
holder
- item's holderitem
- item to trackIllegalArgumentException
- if either parameter is nullpublic void poll()
Applications should invoke this method periodically to avoid memory leaks.
public void close()
The implementation in CloseableTracker
just invokes reset()
.
close
in interface Closeable
close
in interface AutoCloseable
public void reset()
Results in the forced closing of all unclosed items associated with this instance.
This instance may be reused after invoking this method.
protected void exceptionDuringClose(Closeable item, Throwable e)
close()
and item.
The implementation in CloseableTracker
just logs the exception at debug level and returns.
item
- item that was closede
- exeption thrownCopyright © 2022. All rights reserved.