--- /dev/null 2015-05-31 08:17:06.662928244 +0200 +++ new/src/java.base/share/classes/java/lang/ref/ReferenceHandling.java 2015-05-31 18:39:05.980595029 +0200 @@ -0,0 +1,124 @@ +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 executing Finalizer(s), Cleaner(s) and + * enqueuing other Reference(s). + */ +final class ReferenceHandling { + + private static final ForkJoinPool pool = createPool(); + + /** + * Starts handling of references. Called from {@code Reference.} + * after VM has booted. + */ + static void start() { + // triggers class initialization if not already initialized + pool.getClass(); + } + + /** + * Called from {@link Finalizer#runFinalization()} as part of forked secondary + * finalizer thread to run all pending finalizers. We just help the ForkJoinPool + * by waiting for it 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. + */ + static final class PendingChunkHandler extends RecursiveAction { + 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 Finalizer(s). + */ + static final class FinalizerHandler extends RecursiveAction { + private Reference finalizers; + + FinalizerHandler(Reference finalizers) { + this.finalizers = finalizers; + } + + @Override + protected void compute() { + Reference f = finalizers; + if (f != null) { + finalizers = null; + for (Reference n = f.next; ; f = n, n = f.next) { + f.next = f; + ((Finalizer) f).runFinalizer(); + if (n == f) { // last in chunk + break; + } + } + } + } + + void submit() { + if (Thread.currentThread() instanceof ForkJoinWorkerThread) { + // internal submission + fork(); + } else { + // external submission + pool.submit(this); + } + } + } +} +