/** * {@inheritDoc} * * Close this {@code AutoReferenceCountedReaper}, and close any registered * {@link AutoReferenceCounted} instances. */ @Override public void close() { mIsOpen = false; LOG.debug("Closing AutoReferenceCountedReaper with AutoReferenceCounted instances: {}.", mReferences); mExecutorService.shutdownNow(); for (CloseablePhantomRef reference : mReferences) { reference.close(); } mReferences.clear(); }
/** {@inheritDoc} */ @Override public void run() { try { while (true) { CloseablePhantomRef reference = (CloseablePhantomRef) mReferenceQueue.remove(); LOG.debug("Closing enqueued PhantomReference {}.", reference); if (mReferences.remove(reference)) { reference.clear(); // allows referent to be claimed by the GC. reference.close(); } else { // This should not happen LOG.error("Enqueued PhantomReference {} is not registered to this reaper.", reference); } } } catch (InterruptedException e) { // If this thread is interrupted, then die. This happens normally when // AutoReferenceCountedReaper#close is called. // Restore the interrupted status Thread.currentThread().interrupt(); } } }
/** * Register an {@link AutoReferenceCounted} instance to be cleaned up by this * {@code AutoReferenceCountedReaper} when the {@link AutoReferenceCounted} is determined by * the JVM to no longer be reachable. * * @param autoReferenceCountable to be registered to this reaper. */ public void registerAutoReferenceCounted(AutoReferenceCounted autoReferenceCountable) { Preconditions.checkState(mIsOpen, "cannot register an AutoReferenceCounted to a closed AutoReferenceCountedReaper."); LOG.debug("Registering AutoReferenceCounted {}.", autoReferenceCountable); mReferences.add( new CloseablePhantomRef( autoReferenceCountable, mReferenceQueue, autoReferenceCountable.getCloseableResources()) ); }