--- old/src/java.base/share/classes/java/lang/ref/Cleaner.java 2016-04-02 12:52:59.480646587 +0200 +++ new/src/java.base/share/classes/java/lang/ref/Cleaner.java 2016-04-02 12:52:59.393648094 +0200 @@ -29,7 +29,6 @@ import java.util.Objects; import java.util.concurrent.ThreadFactory; -import java.util.function.Function; /** * {@code Cleaner} manages a set of object references and corresponding cleaning actions. @@ -128,28 +127,7 @@ * All cleaning actions registered to a cleaner should be mutually compatible. * @since 9 */ -public final class Cleaner { - - /** - * The Cleaner implementation. - */ - final CleanerImpl impl; - - static { - CleanerImpl.setCleanerImplAccess(new Function() { - @Override - public CleanerImpl apply(Cleaner cleaner) { - return cleaner.impl; - } - }); - } - - /** - * Construct a Cleaner implementation and start it. - */ - private Cleaner() { - impl = new CleanerImpl(); - } +public interface Cleaner { /** * Returns a new {@code Cleaner}. @@ -170,10 +148,8 @@ * @throws SecurityException if the current thread is not allowed to * create or start the thread. */ - public static Cleaner create() { - Cleaner cleaner = new Cleaner(); - cleaner.impl.start(cleaner, null); - return cleaner; + static Cleaner create() { + return new CleanerImpl(null); } /** @@ -197,11 +173,9 @@ * @throws SecurityException if the current thread is not allowed to * create or start the thread. */ - public static Cleaner create(ThreadFactory threadFactory) { + static Cleaner create(ThreadFactory threadFactory) { Objects.requireNonNull(threadFactory, "threadFactory"); - Cleaner cleaner = new Cleaner(); - cleaner.impl.start(cleaner, threadFactory); - return cleaner; + return new CleanerImpl(threadFactory); } /** @@ -214,18 +188,14 @@ * @param action a {@code Runnable} to invoke when the object becomes phantom reachable * @return a {@code Cleanable} instance */ - public Cleanable register(Object obj, Runnable action) { - Objects.requireNonNull(obj, "obj"); - Objects.requireNonNull(action, "action"); - return new CleanerImpl.PhantomCleanableRef(obj, this, action); - } + Cleanable register(Object obj, Runnable action); /** * {@code Cleanable} represents an object and a * cleaning action registered in a {@code Cleaner}. * @since 9 */ - public interface Cleanable { + interface Cleanable { /** * Unregisters the cleanable and invokes the cleaning action. * The cleanable's cleaning action is invoked at most once --- old/src/java.base/share/classes/jdk/internal/ref/CleanerImpl.java 2016-04-02 12:52:59.749641926 +0200 +++ new/src/java.base/share/classes/jdk/internal/ref/CleanerImpl.java 2016-04-02 12:52:59.638643849 +0200 @@ -25,133 +25,130 @@ package jdk.internal.ref; +import jdk.internal.misc.InnocuousThread; + import java.lang.ref.Cleaner; -import java.lang.ref.Cleaner.Cleanable; import java.lang.ref.ReferenceQueue; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.Objects; 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}. + * CleanerImpl is the implementation of {@link Cleaner}. */ -public final class CleanerImpl implements Runnable { - - /** - * An object to access the CleanerImpl from a Cleaner; set by Cleaner init. - */ - private static Function cleanerImplAccess = null; - - /** - * Heads of a CleanableList for each reference type. - */ - final PhantomCleanable phantomCleanableList; - - final WeakCleanable weakCleanableList; - - final SoftCleanable softCleanableList; +public class CleanerImpl implements Cleaner { - // The ReferenceQueue of pending cleaning actions - final ReferenceQueue queue; + final Task task; - /** - * Called by Cleaner static initialization to provide the function - * to map from Cleaner to CleanerImpl. - * @param access a function to map from Cleaner to CleanerImpl - */ - public static void setCleanerImplAccess(Function access) { - if (cleanerImplAccess == null) { - cleanerImplAccess = access; - } else { - throw new InternalError("cleanerImplAccess"); - } + public CleanerImpl(ThreadFactory threadFactory) { + task = new Task(); + task.start(this, threadFactory); } - /** - * Called to get the CleanerImpl for a Cleaner. - * @param cleaner the cleaner - * @return the corresponding CleanerImpl - */ - static CleanerImpl getCleanerImpl(Cleaner cleaner) { - return cleanerImplAccess.apply(cleaner); - } - - /** - * Constructor for CleanerImpl. - */ - public CleanerImpl() { - queue = new ReferenceQueue<>(); - phantomCleanableList = new PhantomCleanableRef(); - weakCleanableList = new WeakCleanableRef(); - softCleanableList = new SoftCleanableRef(); + @Override + public Cleanable register(Object obj, Runnable action) { + Objects.requireNonNull(obj, "obj"); + Objects.requireNonNull(action, "action"); + return new CleanerImpl.PhantomCleanableRef(obj, this, action); } - /** - * Starts the Cleaner implementation. - * Ensure this is the CleanerImpl for the Cleaner. - * When started waits for Cleanables to be queued. - * @param cleaner the cleaner - * @param threadFactory the thread factory - */ - public void start(Cleaner cleaner, ThreadFactory threadFactory) { - 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 CleanerCleanable(cleaner); - - if (threadFactory == null) { - threadFactory = CleanerImpl.InnocuousThreadFactory.factory(); + // package-private access to Task's state + PhantomCleanable phantomCleanableList() { return task.phantomCleanableList; } + WeakCleanable weakCleanableList() { return task.weakCleanableList; } + SoftCleanable softCleanableList() { return task.softCleanableList; } + ReferenceQueue queue() { return task.queue; } + + /** + * CleanerImpl.Task manages a set of object references and corresponding + * cleaning actions and executes them after they are enqueued. + */ + private static final class Task implements Runnable { + /** + * Heads of a CleanableList for each reference type. + */ + final PhantomCleanable phantomCleanableList; + + final WeakCleanable weakCleanableList; + + final SoftCleanable softCleanableList; + + // The ReferenceQueue of pending cleaning actions + final ReferenceQueue queue; + + /** + * Constructor for Task. + */ + Task() { + queue = new ReferenceQueue<>(); + phantomCleanableList = new PhantomCleanableRef(); + weakCleanableList = new WeakCleanableRef(); + softCleanableList = new SoftCleanableRef(); } - // 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); - thread.setDaemon(true); - thread.start(); - } + /** + * Starts the Cleaner implementation. + * Ensure this is the CleanerImpl for the Cleaner. + * When started waits for Cleanables to be queued. + * @param cleaner the cleaner + * @param threadFactory the thread factory + */ + void start(CleanerImpl cleaner, ThreadFactory threadFactory) { + if (cleaner.task != 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 CleanerCleanable(cleaner); - /** - * Process queued Cleanables as long as the cleanable lists are not empty. - * A Cleanable is in one of the lists for each Object and for the Cleaner - * itself. - * Terminates when the Cleaner is no longer reachable and - * has been cleaned and there are no more Cleanable instances - * for which the object is reachable. - *

- * If the thread is a ManagedLocalsThread, the threadlocals - * are erased before each cleanup - */ - @Override - public void run() { - Thread t = Thread.currentThread(); - InnocuousThread mlThread = (t instanceof InnocuousThread) - ? (InnocuousThread) t - : null; - while (!phantomCleanableList.isListEmpty() || - !weakCleanableList.isListEmpty() || - !softCleanableList.isListEmpty()) { - if (mlThread != null) { - // Clear the thread locals - mlThread.eraseThreadLocals(); + if (threadFactory == null) { + threadFactory = CleanerImpl.InnocuousThreadFactory.factory(); } - try { - // Wait for a Ref, with a timeout to avoid getting hung - // due to a race with clear/clean - Cleanable ref = (Cleanable) queue.remove(60 * 1000L); - if (ref != null) { - ref.clean(); + + // 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); + thread.setDaemon(true); + thread.start(); + } + + /** + * Process queued Cleanables as long as the cleanable lists are not empty. + * A Cleanable is in one of the lists for each Object and for the Cleaner + * itself. + * Terminates when the Cleaner is no longer reachable and + * has been cleaned and there are no more Cleanable instances + * for which the object is reachable. + *

+ * If the thread is a ManagedLocalsThread, the threadlocals + * are erased before each cleanup + */ + @Override + public void run() { + Thread t = Thread.currentThread(); + InnocuousThread mlThread = (t instanceof InnocuousThread) + ? (InnocuousThread) t + : null; + while (!phantomCleanableList.isListEmpty() || + !weakCleanableList.isListEmpty() || + !softCleanableList.isListEmpty()) { + if (mlThread != null) { + // Clear the thread locals + mlThread.eraseThreadLocals(); + } + try { + // Wait for a Ref, with a timeout to avoid getting hung + // due to a race with clear/clean + Cleanable ref = (Cleanable) queue.remove(60 * 1000L); + if (ref != null) { + ref.clean(); + } + } catch (Throwable e) { + // ignore exceptions from the cleanup action + // (including interruption of cleanup thread) } - } catch (Throwable e) { - // ignore exceptions from the cleanup action - // (including interruption of cleanup thread) } } } --- old/src/java.base/share/classes/jdk/internal/ref/PhantomCleanable.java 2016-04-02 12:53:00.063636486 +0200 +++ new/src/java.base/share/classes/jdk/internal/ref/PhantomCleanable.java 2016-04-02 12:52:59.945638530 +0200 @@ -63,8 +63,8 @@ * @param cleaner the {@code Cleaner} to register with */ public PhantomCleanable(T referent, Cleaner cleaner) { - super(Objects.requireNonNull(referent), CleanerImpl.getCleanerImpl(cleaner).queue); - this.list = CleanerImpl.getCleanerImpl(cleaner).phantomCleanableList; + super(Objects.requireNonNull(referent), ((CleanerImpl)cleaner).queue()); + this.list = ((CleanerImpl)cleaner).phantomCleanableList(); insert(); // Ensure referent and cleaner remain accessible --- old/src/java.base/share/classes/jdk/internal/ref/SoftCleanable.java 2016-04-02 12:53:00.316632102 +0200 +++ new/src/java.base/share/classes/jdk/internal/ref/SoftCleanable.java 2016-04-02 12:53:00.225633679 +0200 @@ -63,8 +63,8 @@ * @param cleaner the {@code Cleaner} to register with */ public SoftCleanable(T referent, Cleaner cleaner) { - super(Objects.requireNonNull(referent), CleanerImpl.getCleanerImpl(cleaner).queue); - list = CleanerImpl.getCleanerImpl(cleaner).softCleanableList; + super(Objects.requireNonNull(referent), ((CleanerImpl)cleaner).queue()); + list = ((CleanerImpl)cleaner).softCleanableList(); insert(); // Ensure referent and cleaner remain accessible --- old/src/java.base/share/classes/jdk/internal/ref/WeakCleanable.java 2016-04-02 12:53:00.585627441 +0200 +++ new/src/java.base/share/classes/jdk/internal/ref/WeakCleanable.java 2016-04-02 12:53:00.489629105 +0200 @@ -63,8 +63,8 @@ * @param cleaner the {@code Cleaner} to register new reference with */ public WeakCleanable(T referent, Cleaner cleaner) { - super(Objects.requireNonNull(referent), CleanerImpl.getCleanerImpl(cleaner).queue); - list = CleanerImpl.getCleanerImpl(cleaner).weakCleanableList; + super(Objects.requireNonNull(referent), ((CleanerImpl)cleaner).queue()); + list = ((CleanerImpl)cleaner).weakCleanableList(); insert(); // Ensure referent and cleaner remain accessible