diff --git a/src/java.base/share/classes/java/lang/ref/Cleaner.java b/src/java.base/share/classes/java/lang/ref/Cleaner.java index 004051a9b89..b9126ad4163 100644 --- a/src/java.base/share/classes/java/lang/ref/Cleaner.java +++ b/src/java.base/share/classes/java/lang/ref/Cleaner.java @@ -38,7 +38,7 @@ import java.util.function.Function; * to run after the cleaner is notified that the object has become * phantom reachable. * The cleaner uses {@link PhantomReference} and {@link ReferenceQueue} to be - * notified when the reachability + * notified when the {@linkplain java.lang.ref##reachability reachability} * changes. *
* Each cleaner operates independently, managing the pending cleaning actions @@ -215,6 +215,14 @@ public final class Cleaner { * Refer to the API Note above for * cautions about the behavior of cleaning actions. * + *
The given object is kept strongly reachable (and therefore not eligible + * for cleaning) during the register() method. + * + *
{@linkplain java.lang.ref##MemoryConsistency Memory consistency effects}:
+ * Actions in a thread prior to calling {@code Cleaner.register()}
+ * happen-before
+ * the cleaning action is run by the Cleaner's thread.
+ *
* @param obj the object to monitor
* @param action a {@code Runnable} to invoke when the object becomes phantom reachable
* @return a {@code Cleanable} instance
diff --git a/src/java.base/share/classes/java/lang/ref/Reference.java b/src/java.base/share/classes/java/lang/ref/Reference.java
index ef4fd1ef20f..f29a293ce02 100644
--- a/src/java.base/share/classes/java/lang/ref/Reference.java
+++ b/src/java.base/share/classes/java/lang/ref/Reference.java
@@ -388,11 +388,19 @@ public abstract sealed class Reference This method is invoked only by Java code; when the garbage collector
- * clears references it does so directly, without invoking this method.
+ * When the garbage collector or the {@link #enqueue()} method clear
+ * references they do so directly, without invoking this method.
+ *
+ * @apiNote
+ * There is a potential race condition with the garbage collector. When this
+ * method is called, the garbage collector may already be in the process of
+ * (or already completed) clearing and/or enqueueing this reference.
+ * Avoid this race by ensuring the referent remains strongly reachable until
+ * after the call to clear(), using {@link #reachabilityFence(Object)} if
+ * necessary.
*/
public void clear() {
clear0();
@@ -470,11 +478,33 @@ public abstract sealed class Reference This method is invoked only by Java code; when the garbage collector
- * enqueues references it does so directly, without invoking this method.
+ * If this reference is registered with a queue but not yet enqueued,
+ * the reference is added to the queue; this method is
+ * successful and returns true.
+ * If this reference is not registered with a queue, or was already enqueued
+ * (by the garbage collector, or a previous call to {@code enqueue}), this
+ * method is unsuccessful and returns false.
+ *
+ * {@linkplain java.lang.ref##MemoryConsistency Memory consistency effects}:
+ * Actions in a thread prior to a successful call to {@code enqueue}
+ * happen-before
+ * the reference is removed from the queue by {@link ReferenceQueue#poll}
+ * or {@link ReferenceQueue#remove}. Unsuccessful calls to
+ * {@code enqueue} have no specified memory consistency effects.
+ *
+ * When this method clears references it does so directly, without
+ * invoking the {@link #clear()} method. When the garbage collector clears
+ * and enqueues references it does so directly, without invoking the
+ * {@link #clear()} method or this method.
+ *
+ * @apiNote
+ * Use of this method allows the registered queue's
+ * {@link ReferenceQueue#poll} and {@link ReferenceQueue#remove} methods
+ * to return this reference even though the referent may still be strongly
+ * reachable.
*
* @return {@code true} if this reference object was successfully
* enqueued; {@code false} if it was already enqueued or if
@@ -511,60 +541,78 @@ public abstract sealed class Reference This method establishes an ordering for strong reachability
* with respect to garbage collection. It controls relations that are
* otherwise only implicit in a program -- the reachability conditions
- * triggering garbage collection. This method is designed for use in
- * uncommon situations of premature finalization where using
- * {@code synchronized} blocks or methods, or using other synchronization
- * facilities are not possible or do not provide the desired control. This
- * method is applicable only when reclamation may have visible effects,
- * which is possible for objects with finalizers (See Section {@jls 12.6}
- * of The Java Language Specification) that
- * are implemented in ways that rely on ordering control for
- * correctness.
+ * triggering garbage collection. This method is applicable only
+ * when reclamation may have visible effects,
+ * such as for objects that use finalizers or {@link Cleaner}, or code that
+ * performs {@linkplain java.lang.ref reference processing}.
+ *
+ * {@linkplain java.lang.ref##MemoryConsistency Memory consistency effects}:
+ * Actions in a thread prior to calling {@code reachabilityFence(x)}
+ * happen-before
+ * the garbage collector clears any reference to {@code x}.
*
* @apiNote
- * Finalization may occur whenever the virtual machine detects that no
- * reference to an object will ever be stored in the heap: The garbage
- * collector may reclaim an object even if the fields of that object are
- * still in use, so long as the object has otherwise become unreachable.
- * This may have surprising and undesirable effects in cases such as the
- * following example in which the bookkeeping associated with a class is
+ * Reference processing or finalization can occur after an object becomes
+ * unreachable. An object can become unreachable when the virtual machine
+ * detects that there is no further need for the object (other than for
+ * running a finalizer). In the course of optimization, the virtual machine
+ * can reorder operations of an object's methods such that the object
+ * becomes unneeded earlier than might naively be expected —
+ * including while a method of the object is still running. For instance,
+ * the VM can move the loading of values from the object's fields
+ * to occur earlier. The object itself is then no longer needed and becomes
+ * unreachable, and the method can continue running using the obtained values.
+ * This may have surprising and undesirable effects when using a Cleaner or
+ * finalizer for cleanup: there is a race between the
+ * program thread running the method, and the cleanup thread running the
+ * Cleaner or finalizer. The cleanup thread could free a
+ * resource, followed by the program thread (still running the method)
+ * attempting to access the now-already-freed resource.
+ * Use of {@code reachabilityFence} can prevent this race by ensuring that the
+ * object remains strongly reachable.
+ *
+ * The following is an example in which the bookkeeping associated with a class is
* managed through array indices. Here, method {@code action} uses a
* {@code reachabilityFence} to ensure that the {@code Resource} object is
* not reclaimed before bookkeeping on an associated
- * {@code ExternalResource} has been performed; in particular here, to
+ * {@code ExternalResource} has been performed; specifically, to
* ensure that the array slot holding the {@code ExternalResource} is not
* nulled out in method {@link Object#finalize}, which may otherwise run
* concurrently.
*
- * It is sometimes possible to better encapsulate use of
- * {@code reachabilityFence}. Continuing the above example, if it were
- * acceptable for the call to method {@code update} to proceed even if the
- * finalizer had already executed (nulling out slot), then you could
- * localize use of {@code reachabilityFence}:
- *
- * Method {@code reachabilityFence} is not required in constructions
* that themselves ensure reachability. For example, because objects that
@@ -612,10 +644,11 @@ public abstract sealed class Reference {@linkplain java.lang.ref##MemoryConsistency Memory consistency effects}:
+ * The enqueueing of a reference to a queue (by the garbage collector, or by a
+ * successful call to {@link Reference#enqueue})
+ * happens-before
+ * the reference is removed from the queue by {@link ReferenceQueue#poll} or
+ * {@link ReferenceQueue#remove}.
+ *
* @param Each reference-object type is implemented by a subclass of the
@@ -58,54 +58,21 @@
* whatever fields and methods are required for its purposes, or it
* may use these subclasses without change.
*
- * The relationship between a registered reference object and its
- * queue is one-sided. That is, a queue does not keep track of the
- * references that are registered with it. If a registered reference
- * becomes unreachable itself, then it will never be enqueued. It is
- * the responsibility of the program using reference objects to ensure
- * that the objects remain reachable for as long as the program is
- * interested in their referents.
- *
- * While some programs will choose to dedicate a thread to
- * removing reference objects from one or more queues and processing
- * them, this is by no means necessary. A tactic that often works
- * well is to examine a reference queue in the course of performing
- * some other fairly-frequent action. For example, a hashtable that
- * uses weak references to implement weak keys could poll its
- * reference queue each time the table is accessed. This is how the
- * {@link java.util.WeakHashMap} class works. Because
- * the {@link java.lang.ref.ReferenceQueue#poll
- * ReferenceQueue.poll} method simply checks an internal data
- * structure, this check will add little overhead to the hashtable
- * access methods.
- *
*
- * Going from strongest to weakest, the different levels of
* reachability reflect the life cycle of an object. They are
* operationally defined as follows:
*
* The relationship between a registered reference object and its
+ * queue is one-sided. That is, a queue does not keep track of the
+ * references that are registered with it. If a registered reference
+ * becomes unreachable itself, then it will never be enqueued. It is
+ * the responsibility of the program to ensure
+ * that reference objects remain reachable for as long as the program is
+ * interested in their referents.
+ *
+ * While some programs will choose to dedicate a thread to
+ * removing reference objects from one or more queues and processing
+ * them, this is by no means necessary. A tactic that often works
+ * well is to examine a reference queue in the course of performing
+ * some other fairly-frequent action. For example, a hashtable that
+ * uses weak references to implement weak keys could poll its
+ * reference queue each time the table is accessed. This is how the
+ * {@link java.util.WeakHashMap} class works. Because
+ * the {@link java.lang.ref.ReferenceQueue#poll
+ * ReferenceQueue.poll} method simply checks an internal data
+ * structure, this check will add little overhead to the hashtable
+ * access methods.
+ *
+ *
+ *
+ * The interaction between references, finalizers, and the garbage collector
+ * also forms a happens-before relationship:
+ *
+ * {@code
+ * {@snippet :
* class Resource {
* private static ExternalResource[] externalResourceArray = ...
*
* int myIndex;
* Resource(...) {
- * myIndex = ...
+ * this.myIndex = ...
* externalResourceArray[myIndex] = ...;
* ...
* }
* protected void finalize() {
- * externalResourceArray[myIndex] = null;
+ * externalResourceArray[this.myIndex] = null;
* ...
* }
* public void action() {
* try {
* // ...
- * int i = myIndex;
+ * int i = this.myIndex; // last use of 'this' Resource in action()
* Resource.update(externalResourceArray[i]);
* } finally {
* Reference.reachabilityFence(this);
@@ -573,36 +621,20 @@ public abstract sealed class Reference
+ * }
+ * }
*
- * Here, the invocation of {@code reachabilityFence} is nonintuitively
+ * The invocation of {@code reachabilityFence} is
* placed after the call to {@code update}, to ensure that the
* array slot is not nulled out by {@link Object#finalize} before the
* update, even if the call to {@code action} was the last use of this
- * object. This might be the case if, for example a usage in a user program
+ * object. This might be the case if, for example, a usage in a user program
* had the form {@code new Resource().action();} which retains no other
- * reference to this {@code Resource}. While probably overkill here,
- * {@code reachabilityFence} is placed in a {@code finally} block to ensure
- * that it is invoked across all paths in the method. In a method with more
- * complex control paths, you might need further precautions to ensure that
- * {@code reachabilityFence} is encountered along all of them.
- *
- * {@code
- * public void action2() {
- * // ...
- * Resource.update(getExternalResource());
- * }
- * private ExternalResource getExternalResource() {
- * ExternalResource ext = externalResourceArray[myIndex];
- * Reference.reachabilityFence(this);
- * return ext;
- * }}
+ * reference to this {@code Resource}.
+ * The {@code reachabilityFence} call is placed in a {@code finally} block to
+ * ensure that it is invoked across all paths in the method. A more complex
+ * method might need further precautions to ensure that
+ * {@code reachabilityFence} is encountered along all code paths.
*
* Package Specification
+ * Reference Objects
*
* A reference object encapsulates a reference to some other
* object so that the reference itself may be examined and manipulated
@@ -44,7 +44,7 @@
* implementing canonicalizing mappings that do not prevent their keys
* (or values) from being reclaimed, and phantom references are for
* scheduling post-mortem cleanup actions.
- * Post-mortem cleanup actions can be registered and managed by a
+ * Post-mortem cleanup actions can also be registered and managed by a
* {@link java.lang.ref.Cleaner}.
*
* Notification
- *
- * A program may request to be notified of changes in an object's
- * reachability by registering an appropriate reference
- * object with a reference queue at the time the reference
- * object is created. Some time after the garbage collector
- * determines that the reachability of the referent has changed to the
- * value corresponding to the type of the reference, it will clear the
- * reference and add it to the associated queue. At this point, the
- * reference is considered to be enqueued. The program may remove
- * references from a queue either by polling or by blocking until a
- * reference becomes available. Reference queues are implemented by
- * the {@link java.lang.ref.ReferenceQueue} class.
- *
- * Reachability
+ * Reachability
*
- * Going from strongest to weakest, the different levels of
+ * A reachable object is any object that can be accessed in any potential
+ * continuing computation from any
+ * {@linkplain java.lang.Thread#isAlive live thread} (as stated in JLS {@jls 12.6.1}).
+ *
+ *
*
- *
*
+ * Notification
+ *
+ * A program may request to be notified of changes in an object's
+ * reachability by registering an appropriate reference
+ * object with a {@link java.lang.ref.ReferenceQueue}.
+ * This is done by providing the reference queue as
+ * a constructor argument when creating the reference object.
+ * Some time after the garbage collector
+ * determines that the reachability of the referent has changed to correspond
+ * with the type of the reference, it will clear the
+ * reference and add it to the associated queue. At this point, the
+ * reference is considered to be enqueued. The program learns of the
+ * referent's change in reachability when the associated reference becomes
+ * available on the queue. The program may remove references from a queue
+ * (that is, dequeue them) using the {@link ReferenceQueue#poll()} or
+ * {@link ReferenceQueue#remove()} methods. Additional state needed to respond to a
+ * referent's change in reachability can be stored in the fields of a custom
+ * reference subclass, and accessed when the reference is returned from the
+ * queue.
+ *
+ * Memory Consistency Properties
+ * Certain interactions between references, reference queues, and the garbage
+ * collector form
+ * happens-before
+ * relationships:
+ *
+ *
+ *
+ *
+ * The above chain of happens-before edges ensures that actions in a
+ * thread prior to a {@link Reference#reachabilityFence Reference.reachabilityFence(x)}
+ * happen-before cleanup code for {@code x} runs on a Cleaner thread.
+ * In particular, changes to the state of {@code x} made before
+ * {@code reachabilityFence(x)} will be visible to the cleanup code running on
+ * a Cleaner thread without additional synchronization.
+ * See JLS {@jls 17.4.5}.
+ *
+ *
+ *
+ *
+ * This ensures that actions in a thread prior to a
+ * {@link Reference#reachabilityFence Reference.reachabilityFence(x)}
+ * happen-before cleanup code for {@code x} runs on a finalizer thread.
+ * In particular, changes to the state of {@code x} made before
+ * {@code reachabilityFence(x)} will be visible to the cleanup code running on
+ * a finalizer thread without additional synchronization.
+ * See JLS {@jls 17.4.5}.
+ *
* @author Mark Reinhold
* @since 1.2
*/