1 package java.lang.ref; 2 3 import java.util.concurrent.ForkJoinPool; 4 import java.util.concurrent.ForkJoinWorkerThread; 5 import java.util.concurrent.RecursiveAction; 6 import java.util.concurrent.TimeUnit; 7 8 /** 9 * A holder for a ForkJoinPool and tasks executing Finalizer(s), Cleaner(s) and 10 * enqueuing other Reference(s). 11 */ 12 final class ReferenceHandling { 13 14 private static final ForkJoinPool pool = createPool(); 15 16 /** 17 * Starts handling of references. Called from {@code Reference.<clinit>} 18 * after VM has booted. 19 */ 20 static void start() { 21 // triggers class initialization if not already initialized 22 pool.getClass(); 23 } 24 25 /** 26 * Called from {@link Finalizer#runFinalization()} as part of forked secondary 27 * finalizer thread to run all pending finalizers. We just help the ForkJoinPool 28 * by waiting for it to quiesce. 29 */ 30 static void runFinalization() { 31 do { 32 } while (!pool.awaitQuiescence(5, TimeUnit.SECONDS)); 33 } 34 35 /** 36 * Creates new ForkJoinPool for handling the references. 37 */ 38 private static ForkJoinPool createPool() { 39 String refHandlingThreadsString = 40 System.getProperty("java.lang.ref.referenceHandlingThreads", "1"); 41 int referenceHandlingThreads; 42 try { 43 referenceHandlingThreads = Math.min( 44 Runtime.getRuntime().availableProcessors(), 45 Math.max(1, Integer.parseInt(refHandlingThreadsString)) 46 ); 47 } catch (NumberFormatException e) { 48 referenceHandlingThreads = 1; 49 } 50 return new ForkJoinPool( 51 referenceHandlingThreads, 52 ForkJoinPool.defaultForkJoinWorkerThreadFactory, 53 null, 54 true 55 ); 56 } 57 58 /** 59 * A task that handles one chunk of references. 60 */ 61 static final class PendingChunkHandler extends RecursiveAction { 62 private Reference<?> chunk; 63 64 PendingChunkHandler(Reference<?> chunk) { 65 this.chunk = chunk; 66 } 67 68 @Override 69 protected void compute() { 70 Reference<?> r = this.chunk; 71 if (r != null) { 72 this.chunk = null; 73 Reference.handlePendingChunk(r); 74 } 75 } 76 77 void submit() { 78 if (Thread.currentThread() instanceof ForkJoinWorkerThread) { 79 // internal submission 80 fork(); 81 } else { 82 // external submission 83 pool.submit(this); 84 } 85 } 86 } 87 88 /** 89 * A task for handling a chunk of Finaliz(ato|e)r(s). 90 */ 91 static final class FinalizrHandler extends RecursiveAction { 92 private Reference<?> finalzrs; 93 94 FinalizrHandler(Reference<?> finalzrs) { 95 this.finalzrs = finalzrs; 96 } 97 98 @Override 99 protected void compute() { 100 Reference<?> f = finalzrs; 101 if (f != null) { 102 finalzrs = null; 103 for (Reference<?> n = f.next; ; f = n, n = f.next) { 104 f.next = f; 105 // Finalizer and Finalizator are both Runnable(s) 106 ((Runnable) f).run(); 107 if (n == f) { // last in chunk 108 break; 109 } 110 } 111 } 112 } 113 114 void submit() { 115 if (Thread.currentThread() instanceof ForkJoinWorkerThread) { 116 // internal submission 117 fork(); 118 } else { 119 // external submission 120 pool.submit(this); 121 } 122 } 123 } 124 } 125