< 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 >