package java.lang.ref; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinWorkerThread; import java.util.concurrent.RecursiveAction; import java.util.concurrent.TimeUnit; /** * A holder for a ForkJoinPool and tasks for handling pending and * Cleaner references. */ final class ReferenceHandling { private static final ForkJoinPool pool = createPool(); /** * Called from {@link Finalizer#runFinalization()} as part of forked secondary * finalizer thread to run all pending AutoRunnable(s). We just help the ForkJoinPool * by lending current thread while waiting for pool to quiesce. */ static void runFinalization() { do { } while (!pool.awaitQuiescence(5, TimeUnit.SECONDS)); } /** * Creates new ForkJoinPool for handling the references. */ private static ForkJoinPool createPool() { String refHandlingThreadsString = System.getProperty("java.lang.ref.referenceHandlingThreads", "1"); int referenceHandlingThreads; try { referenceHandlingThreads = Math.min( Runtime.getRuntime().availableProcessors(), Math.max(1, Integer.parseInt(refHandlingThreadsString)) ); } catch (NumberFormatException e) { referenceHandlingThreads = 1; } return new ForkJoinPool( referenceHandlingThreads, ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true ); } /** * A task that handles one chunk of references. A chunk * is linked using 'discovered' links. Last in chunk is linked to 'null'. */ static final class PendingChunkHandler extends RecursiveAction { private static final long serialVersionUID = 1L; private Reference chunk; PendingChunkHandler(Reference chunk) { this.chunk = chunk; } @Override protected void compute() { Reference r = this.chunk; if (r != null) { this.chunk = null; Reference.handlePendingChunk(r); } } void submit() { if (Thread.currentThread() instanceof ForkJoinWorkerThread) { // internal submission fork(); } else { // external submission pool.submit(this); } } } /** * A task for handling a chunk of j.l.r.Cleaner Reference(s). A chunk * is linked using 'discovered' links. Last in chunk is linked to null. */ static final class CleanersHandler extends RecursiveAction { private static final long serialVersionUID = 1L; private Reference cleaners; CleanersHandler(Reference cleaners) { this.cleaners = cleaners; } @Override protected void compute() { Reference c = cleaners; if (c != null) { cleaners = null; Reference.handleCleaners(c); } } void submit() { if (Thread.currentThread() instanceof ForkJoinWorkerThread) { // internal submission fork(); } else { // external submission pool.submit(this); } } } }