--- /dev/null 2015-06-06 09:45:45.596162458 +0200
+++ new/src/java.base/share/classes/java/lang/ref/Finalizator.java 2015-06-06 15:34:11.577915687 +0200
@@ -0,0 +1,163 @@
+package java.lang.ref;
+
+import java.util.Objects;
+import java.util.function.Consumer;
+
+/**
+ *
Finalizator provides an alternative form of finalization which can be more
+ * efficiently combined with (almost) regular manual cleanup where it serves as
+ * a last-resort cleanup mechanism when manual cleanup is not performed.
+ *
+ * Instead of overriding the Object's {@link #finalize()} method, a class
+ * arranges in it's constructor(s) to {@link #create(Object, Consumer) create} a
+ * {@code Finalizator} object which is used by GC to track the reachability of
+ * given {@code finalizee} and invoke given {@code thunk} with it when such
+ * {@code finalizee} becomes unreachable.
+ *
+ * {@code Finalizator} can be {@link #run() invoked} manually by user code that
+ * decides to perform cleanup even before GC invokes it. The 1st invocation of
+ * {@link #run()} method performs the cleanup by invoking the {@code thunk},
+ * subsequent invocations are ignored.
+ *
+ * After the cleanup is performed, the
+ * {@code Finalizator} is {@link #clear() cleared} which breaks the links between:
+ *
+ * - finalizator and finalizee,
+ * - finalizator and thunk,
+ * - platform and finalizator
+ *
+ * In the absence of other links, finalizator, finalizee and thunk become
+ * unreachable and eligible for GC.
+ *
+ * Here's an example of a classic finalizable class:
+ *
{@code
+ * public class Classic {
+ * @Override
+ * protected void finalize() {
+ * // clean-up actions invoked at most once...
+ * }
+ * }
+ * }
+ *
+ * And this is an alternative using {@code Finalizator}, combining finalization
+ * with manual cleanup:
+ *
{@code
+ * public class Alternative {
+ * private final Finalizator finalizator =
+ * Finalizator.create(this, Alternative::cleanup);
+ *
+ * void cleanup() {
+ * // clean-up actions invoked at most once...
+ * }
+ *
+ * // manually triggered cleanup
+ * public void close() {
+ * finalizator.run();
+ * }
+ * }
+ * }
+ *
+ * @param the type of finalizee tracked by Finalizator
+ * @since 1.9
+ */
+public final class Finalizator extends Finalizer implements Runnable {
+
+ private Consumer super T> thunk;
+
+ /**
+ * Creates and returns an instance of Finalizator used by GC to track given
+ * {@code finalizee} and invoke given {@code thunk} with it when the
+ * finalizee becomes unreachable.
+ *
+ * @param finalizee the instance to track it's reachability
+ * @param thunk a {@link Consumer} which is invoked and passed the
+ * {@code finalizee} when it becomes unreachable.
+ * @throws NullPointerException if either {@code finalizee} of {@code thunk}
+ * are null
+ */
+ public static Finalizator create(T finalizee, Consumer super T> thunk) {
+ Objects.requireNonNull(finalizee);
+ Objects.requireNonNull(thunk);
+ int rnd = nextSecondarySeed();
+ int index = (rnd >>> 1) & (unfinalized.length - 1);
+ Finalizator finalizator = new Finalizator<>(finalizee, index, thunk);
+ unfinalized[index].link(finalizator, (rnd & 1) == 0);
+ return finalizator;
+ }
+
+ private Finalizator(T finalizee, int listIndex, Consumer super T> thunk) {
+ super(finalizee, listIndex);
+ this.thunk = thunk;
+ }
+
+ /**
+ * Invoked by GC when the tracked finalizee becomes unreachable or
+ * by user code at any time.
+ * It invokes the finalizator's thunk with the finalizee if this
+ * Finalizator has not been {@link #clear() cleared} before that. If invoked
+ * multiple times, only the 1st invocation results in the invocation
+ * of the thunk. The finalizator releases the reference to the thunk and
+ * finalizee upon 1st invocation of this method regardless of whether
+ * it was performed by GC or by user code.
+ */
+ @Override
+ public void run() {
+ super.run();
+ }
+
+ /**
+ * Invoke the {@link #thunk} passing the {@code finalizee} to it.
+ */
+ @Override
+ void invokeFinalizee(T finalizee) throws Throwable {
+ Consumer super T> thunk = this.thunk;
+ this.thunk = null;
+ thunk.accept(finalizee);
+ finalizee = null;
+ }
+
+ /**
+ * Returns {@code null} to prevent unwanted retention of the tracked
+ * {@code finalizee}.
+ *
+ * @return {@code null}
+ */
+ @Override
+ public T get() {
+ return null;
+ }
+
+ /**
+ * Finalizator is not registered with a reference queue when created,
+ * so this method always returns {@code false}.
+ *
+ * @return {@code false}
+ */
+ @Override
+ public boolean isEnqueued() {
+ return false;
+ }
+
+ /**
+ * Finalizator is not registered with a reference queue when created,
+ * so this method does nothing and always returns {@code false}.
+ *
+ * @return {@code false}
+ */
+ @Override
+ public boolean enqueue() {
+ return false;
+ }
+
+ /**
+ * Clears this Finalizator and releases it's tracked {@code finalizee} and
+ * it's {@code thunk} if they have not been released yet.
+ * Invoking this method does not invoke the Finalizator's {@code thunk}.
+ * It prevents from {@link #run() running} the {@code thunk} in the future
+ * if it has not been run yet.
+ */
+ @Override
+ public void clear() {
+ super.clear();
+ }
+}