Package com.google.common.base
Class FinalizableReferenceQueue
- java.lang.Object
-
- com.google.common.base.FinalizableReferenceQueue
-
- All Implemented Interfaces:
java.io.Closeable
,java.lang.AutoCloseable
public class FinalizableReferenceQueue extends java.lang.Object implements java.io.Closeable
A reference queue with an associated background thread that dequeues references and invokesFinalizableReference.finalizeReferent()
on them.Keep a strong reference to this object until all of the associated referents have been finalized. If this object is garbage collected earlier, the backing thread will not invoke
finalizeReferent()
on the remaining references.As an example of how this is used, imagine you have a class
MyServer
that creates a aServerSocket
, and you would like to ensure that theServerSocket
is closed even if theMyServer
object is garbage-collected without calling itsclose
method. You could use a finalizer to accomplish this, but that has a number of well-known problems. Here is how you might use this class instead:public class MyServer implements Closeable { private static final FinalizableReferenceQueue frq = new FinalizableReferenceQueue(); // You might also share this between several objects. private static final Set<Reference<?>> references = Sets.newConcurrentHashSet(); // This ensures that the FinalizablePhantomReference itself is not garbage-collected. private final ServerSocket serverSocket; private MyServer(...) { ... this.serverSocket = new ServerSocket(...); ... } public static MyServer create(...) { MyServer myServer = new MyServer(...); final ServerSocket serverSocket = myServer.serverSocket; Reference<?> reference = new FinalizablePhantomReference<MyServer>(myServer, frq) { public void finalizeReferent() { references.remove(this): if (!serverSocket.isClosed()) { ...log a message about how nobody called close()... try { serverSocket.close(); } catch (IOException e) { ... } } } }; references.add(reference); return myServer; } public void close() { serverSocket.close(); } }
- Since:
- 2.0
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description (package private) static class
FinalizableReferenceQueue.DecoupledLoader
Try to load Finalizer in its own class loader.(package private) static class
FinalizableReferenceQueue.DirectLoader
Loads Finalizer directly using the current class loader.(package private) static interface
FinalizableReferenceQueue.FinalizerLoader
Loads Finalizer.class.(package private) static class
FinalizableReferenceQueue.SystemLoader
Tries to load Finalizer from the system class loader.
-
Field Summary
Fields Modifier and Type Field Description private static java.lang.String
FINALIZER_CLASS_NAME
(package private) java.lang.ref.PhantomReference<java.lang.Object>
frqRef
private static java.util.logging.Logger
logger
(package private) java.lang.ref.ReferenceQueue<java.lang.Object>
queue
The actual reference queue that our background thread will poll.private static java.lang.reflect.Method
startFinalizer
Reference to Finalizer.startFinalizer().(package private) boolean
threadStarted
Whether or not the background thread started successfully.
-
Constructor Summary
Constructors Constructor Description FinalizableReferenceQueue()
Constructs a new queue.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description (package private) void
cleanUp()
Repeatedly dequeues references from the queue and invokesFinalizableReference.finalizeReferent()
on them until the queue is empty.void
close()
(package private) static java.lang.reflect.Method
getStartFinalizer(java.lang.Class<?> finalizer)
Looks up Finalizer.startFinalizer().private static java.lang.Class<?>
loadFinalizer(FinalizableReferenceQueue.FinalizerLoader... loaders)
Iterates through the given loaders until it finds one that can load Finalizer.
-
-
-
Field Detail
-
logger
private static final java.util.logging.Logger logger
-
FINALIZER_CLASS_NAME
private static final java.lang.String FINALIZER_CLASS_NAME
- See Also:
- Constant Field Values
-
startFinalizer
private static final java.lang.reflect.Method startFinalizer
Reference to Finalizer.startFinalizer().
-
queue
final java.lang.ref.ReferenceQueue<java.lang.Object> queue
The actual reference queue that our background thread will poll.
-
frqRef
final java.lang.ref.PhantomReference<java.lang.Object> frqRef
-
threadStarted
final boolean threadStarted
Whether or not the background thread started successfully.
-
-
Method Detail
-
close
public void close()
- Specified by:
close
in interfacejava.lang.AutoCloseable
- Specified by:
close
in interfacejava.io.Closeable
-
cleanUp
void cleanUp()
Repeatedly dequeues references from the queue and invokesFinalizableReference.finalizeReferent()
on them until the queue is empty. This method is a no-op if the background thread was created successfully.
-
loadFinalizer
private static java.lang.Class<?> loadFinalizer(FinalizableReferenceQueue.FinalizerLoader... loaders)
Iterates through the given loaders until it finds one that can load Finalizer.- Returns:
- Finalizer.class
-
getStartFinalizer
static java.lang.reflect.Method getStartFinalizer(java.lang.Class<?> finalizer)
Looks up Finalizer.startFinalizer().
-
-