--- /dev/null 2015-06-17 09:49:50.124106881 +0200 +++ new/src/java.base/share/classes/java/lang/ref/ReferenceHandling.java 2015-06-22 11:04:04.278384377 +0200 @@ -0,0 +1,114 @@ +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); + } + } + } +}