< prev index next >

src/java.base/share/classes/jdk/internal/ref/CleanerImpl.java

Print this page

        

@@ -29,19 +29,20 @@
 import java.lang.ref.Cleaner.Cleanable;
 import java.lang.ref.ReferenceQueue;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Function;
 
 import jdk.internal.misc.InnocuousThread;
 
 /**
  * CleanerImpl manages a set of object references and corresponding cleaning actions.
  * CleanerImpl provides the functionality of {@link java.lang.ref.Cleaner}.
  */
-public final class CleanerImpl {
+public final class CleanerImpl implements Runnable {
 
     /**
      * An object to access the CleanerImpl from a Cleaner; set by Cleaner init.
      */
     private static Function<Cleaner, CleanerImpl> cleanerImplAccess = null;

@@ -101,20 +102,20 @@
         if (getCleanerImpl(cleaner) != this) {
             throw new AssertionError("wrong cleaner");
         }
         // schedule a nop cleaning action for the cleaner, so the associated thread
         // will continue to run at least until the cleaner is reclaimable.
-        new PhantomCleanableRef(cleaner, cleaner, () -> {});
+        new CleanerCleanable(cleaner);
 
         if (threadFactory == null) {
             threadFactory = CleanerImpl.InnocuousThreadFactory.factory();
         }
 
         // now that there's at least one cleaning action, for the cleaner,
         // we can start the associated thread, which runs until
         // all cleaning actions have been run.
-        Thread thread = threadFactory.newThread(this::run);
+        Thread thread = threadFactory.newThread(this);
         thread.setDaemon(true);
         thread.start();
     }
 
     /**

@@ -126,11 +127,12 @@
      * for which the object is reachable.
      * <p>
      * If the thread is a ManagedLocalsThread, the threadlocals
      * are erased before each cleanup
      */
-    private void run() {
+    @Override
+    public void run() {
         Thread t = Thread.currentThread();
         InnocuousThread mlThread = (t instanceof InnocuousThread)
                 ? (InnocuousThread) t
                 : null;
         while (!phantomCleanableList.isListEmpty() ||

@@ -145,14 +147,13 @@
                 // due to a race with clear/clean
                 Cleanable ref = (Cleanable) queue.remove(60 * 1000L);
                 if (ref != null) {
                     ref.clean();
                 }
-            } catch (InterruptedException i) {
-                continue;   // ignore the interruption
             } catch (Throwable e) {
                 // ignore exceptions from the cleanup action
+                // (including interruption of cleanup thread)
             }
         }
     }
 
     /**

@@ -318,16 +319,34 @@
 
         static ThreadFactory factory() {
             return factory;
         }
 
+        final AtomicInteger cleanerThreadNumber = new AtomicInteger();
+
         public Thread newThread(Runnable r) {
-            return AccessController.doPrivileged((PrivilegedAction<Thread>) () -> {
+            return AccessController.doPrivileged(new PrivilegedAction<Thread>() {
+                @Override
+                public Thread run() {
                 Thread t = new InnocuousThread(r);
                 t.setPriority(Thread.MAX_PRIORITY - 2);
-                t.setName("Cleaner-" + t.getId());
+                    t.setName("Cleaner-" + cleanerThreadNumber.getAndIncrement());
                 return t;
+                }
             });
         }
     }
 
+    /**
+     * A PhantomCleanable implementation for tracking the Cleaner itself.
+     */
+    static final class CleanerCleanable extends PhantomCleanable<Cleaner> {
+        CleanerCleanable(Cleaner cleaner) {
+            super(cleaner, cleaner);
+        }
+
+        @Override
+        protected void performCleanup() {
+            // no action
+        }
+    }
 }
< prev index next >