mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +02:00
8314480: Memory ordering spec updates in java.lang.ref
Reviewed-by: dholmes, alanb, darcy
This commit is contained in:
parent
9fd0e7349e
commit
2cae9a0397
4 changed files with 218 additions and 105 deletions
|
@ -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 <a href="package-summary.html#reachability">reachability</a>
|
||||
* notified when the {@linkplain java.lang.ref##reachability reachability}
|
||||
* changes.
|
||||
* <p>
|
||||
* Each cleaner operates independently, managing the pending cleaning actions
|
||||
|
@ -215,6 +215,14 @@ public final class Cleaner {
|
|||
* Refer to the <a href="#compatible-cleaners">API Note</a> above for
|
||||
* cautions about the behavior of cleaning actions.
|
||||
*
|
||||
* <p>The given object is kept strongly reachable (and therefore not eligible
|
||||
* for cleaning) during the register() method.
|
||||
*
|
||||
* <p>{@linkplain java.lang.ref##MemoryConsistency Memory consistency effects}:
|
||||
* Actions in a thread prior to calling {@code Cleaner.register()}
|
||||
* <a href="{@docRoot}/java.base/java/util/concurrent/package-summary.html#MemoryVisibility"><i>happen-before</i></a>
|
||||
* 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
|
||||
|
|
|
@ -388,11 +388,19 @@ public abstract sealed class Reference<T>
|
|||
private native boolean refersTo0(Object o);
|
||||
|
||||
/**
|
||||
* Clears this reference object. Invoking this method will not cause this
|
||||
* object to be enqueued.
|
||||
* Clears this reference object. Invoking this method does not enqueue this
|
||||
* object, and the garbage collector will not clear or enqueue this object.
|
||||
*
|
||||
* <p> This method is invoked only by Java code; when the garbage collector
|
||||
* clears references it does so directly, without invoking this method.
|
||||
* <p>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<T>
|
|||
}
|
||||
|
||||
/**
|
||||
* Clears this reference object and adds it to the queue with which
|
||||
* it is registered, if any.
|
||||
* Clears this reference object, then attempts to add it to the queue with
|
||||
* which it is registered, if any.
|
||||
*
|
||||
* <p> This method is invoked only by Java code; when the garbage collector
|
||||
* enqueues references it does so directly, without invoking this method.
|
||||
* <p>If this reference is registered with a queue but not yet enqueued,
|
||||
* the reference is added to the queue; this method is
|
||||
* <b><i>successful</i></b> 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 <b><i>unsuccessful</i></b> and returns false.
|
||||
*
|
||||
* <p>{@linkplain java.lang.ref##MemoryConsistency Memory consistency effects}:
|
||||
* Actions in a thread prior to a <b><i>successful</i></b> call to {@code enqueue}
|
||||
* <a href="{@docRoot}/java.base/java/util/concurrent/package-summary.html#MemoryVisibility"><i>happen-before</i></a>
|
||||
* the reference is removed from the queue by {@link ReferenceQueue#poll}
|
||||
* or {@link ReferenceQueue#remove}. <b><i>Unsuccessful</i></b> calls to
|
||||
* {@code enqueue} have no specified memory consistency effects.
|
||||
*
|
||||
* <p> 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<T>
|
|||
}
|
||||
|
||||
/**
|
||||
* Ensures that the object referenced by the given reference remains
|
||||
* <a href="package-summary.html#reachability"><em>strongly reachable</em></a>,
|
||||
* regardless of any prior actions of the program that might otherwise cause
|
||||
* the object to become unreachable; thus, the referenced object is not
|
||||
* Ensures that the given object remains
|
||||
* <a href="package-summary.html#reachability"><em>strongly reachable</em></a>.
|
||||
* This reachability is assured regardless of any optimizing transformations
|
||||
* the virtual machine may perform that might otherwise allow the object to
|
||||
* become unreachable (see JLS {@jls 12.6.1}). Thus, the given object is not
|
||||
* reclaimable by garbage collection at least until after the invocation of
|
||||
* this method. Invocation of this method does not itself initiate garbage
|
||||
* collection or finalization.
|
||||
* this method. References to the given object will not be cleared (or
|
||||
* enqueued, if applicable) by the garbage collector until after invocation
|
||||
* of this method.
|
||||
* Invocation of this method does not itself initiate reference processing,
|
||||
* garbage collection, or finalization.
|
||||
*
|
||||
* <p> This method establishes an ordering for <em>strong reachability</em>
|
||||
* 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 <cite>The Java Language Specification</cite>) 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}.
|
||||
*
|
||||
* <p>{@linkplain java.lang.ref##MemoryConsistency Memory consistency effects}:
|
||||
* Actions in a thread prior to calling {@code reachabilityFence(x)}
|
||||
* <a href="{@docRoot}/java.base/java/util/concurrent/package-summary.html#MemoryVisibility"><i>happen-before</i></a>
|
||||
* 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 <em>values</em> 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.
|
||||
* <p>
|
||||
* 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.
|
||||
*
|
||||
* <pre> {@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<T>
|
|||
* private static void update(ExternalResource ext) {
|
||||
* ext.status = ...;
|
||||
* }
|
||||
* }}</pre>
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Here, the invocation of {@code reachabilityFence} is nonintuitively
|
||||
* The invocation of {@code reachabilityFence} is
|
||||
* placed <em>after</em> 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.
|
||||
*
|
||||
* <p> 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}:
|
||||
*
|
||||
* <pre> {@code
|
||||
* public void action2() {
|
||||
* // ...
|
||||
* Resource.update(getExternalResource());
|
||||
* }
|
||||
* private ExternalResource getExternalResource() {
|
||||
* ExternalResource ext = externalResourceArray[myIndex];
|
||||
* Reference.reachabilityFence(this);
|
||||
* return ext;
|
||||
* }}</pre>
|
||||
* 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.
|
||||
*
|
||||
* <p> 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<T>
|
|||
* blocks. (Further, such blocks must not include infinite loops, or
|
||||
* themselves be unreachable, which fall into the corner case exceptions to
|
||||
* the "in general" disclaimer.) However, method {@code reachabilityFence}
|
||||
* remains a better option in cases where this approach is not as efficient,
|
||||
* remains a better option in cases where synchronization is not as efficient,
|
||||
* desirable, or possible; for example because it would encounter deadlock.
|
||||
*
|
||||
* @param ref the reference. If {@code null}, this method has no effect.
|
||||
* @param ref the reference to the object to keep strongly reachable. If
|
||||
* {@code null}, this method has no effect.
|
||||
* @since 9
|
||||
*/
|
||||
@ForceInline
|
||||
|
|
|
@ -34,6 +34,14 @@ import jdk.internal.misc.VM;
|
|||
/**
|
||||
* Reference queues, to which registered reference objects are appended by the
|
||||
* garbage collector after the appropriate reachability changes are detected.
|
||||
*
|
||||
* <p>{@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})
|
||||
* <a href="{@docRoot}/java.base/java/util/concurrent/package-summary.html#MemoryVisibility"><i>happens-before</i></a>
|
||||
* the reference is removed from the queue by {@link ReferenceQueue#poll} or
|
||||
* {@link ReferenceQueue#remove}.
|
||||
*
|
||||
* @param <T> the type of the reference object
|
||||
*
|
||||
* @author Mark Reinhold
|
||||
|
@ -175,6 +183,7 @@ public class ReferenceQueue<T> {
|
|||
*
|
||||
* @return A reference object, if one was immediately available,
|
||||
* otherwise {@code null}
|
||||
* @see java.lang.ref.Reference#enqueue()
|
||||
*/
|
||||
public Reference<? extends T> poll() {
|
||||
if (headIsNull())
|
||||
|
@ -206,6 +215,8 @@ public class ReferenceQueue<T> {
|
|||
*
|
||||
* @throws InterruptedException
|
||||
* If the timeout wait is interrupted
|
||||
*
|
||||
* @see java.lang.ref.Reference#enqueue()
|
||||
*/
|
||||
public Reference<? extends T> remove(long timeout) throws InterruptedException {
|
||||
if (timeout < 0)
|
||||
|
@ -227,6 +238,7 @@ public class ReferenceQueue<T> {
|
|||
*
|
||||
* @return A reference object, blocking until one becomes available
|
||||
* @throws InterruptedException If the wait is interrupted
|
||||
* @see java.lang.ref.Reference#enqueue()
|
||||
*/
|
||||
public Reference<? extends T> remove() throws InterruptedException {
|
||||
lock.lock();
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
* after the collector has determined that the reachability of a given
|
||||
* object has changed.
|
||||
*
|
||||
*<h2>Package Specification</h2>
|
||||
* <h2>Reference Objects</h2>
|
||||
*
|
||||
* A <em>reference object</em> 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}.
|
||||
*
|
||||
* <p> 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.
|
||||
*
|
||||
* <h3>Notification</h3>
|
||||
*
|
||||
* A program may request to be notified of changes in an object's
|
||||
* reachability by <em>registering</em> an appropriate reference
|
||||
* object with a <em>reference queue</em> 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 <em>enqueued</em>. 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.
|
||||
*
|
||||
* <p> 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.
|
||||
*
|
||||
* <p> 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.
|
||||
*
|
||||
* <a id="reachability"></a>
|
||||
* <h3>Reachability</h3>
|
||||
* <h2>Reachability</h2>
|
||||
*
|
||||
* Going from strongest to weakest, the different levels of
|
||||
* A <em>reachable</em> 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}).
|
||||
*
|
||||
* <p> Going from strongest to weakest, the different levels of
|
||||
* reachability reflect the life cycle of an object. They are
|
||||
* operationally defined as follows:
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li> An object is <em>strongly reachable</em> if it can be reached
|
||||
* by some thread without traversing any reference objects. A
|
||||
* newly-created object is strongly reachable by the thread that
|
||||
* created it.
|
||||
* <li> An object is <em>strongly reachable</em> if it is reachable and if it
|
||||
* can be accessed without traversing the referent of a Reference object.
|
||||
*
|
||||
* <li> An object is <em>softly reachable</em> if it is not strongly
|
||||
* reachable but can be reached by traversing a soft reference.
|
||||
|
@ -125,6 +92,99 @@
|
|||
*
|
||||
* </ul>
|
||||
*
|
||||
* <h2>Notification</h2>
|
||||
*
|
||||
* A program may request to be notified of changes in an object's
|
||||
* reachability by <em>registering</em> 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 <em>enqueued</em>. 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, <em>dequeue</em> 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.
|
||||
*
|
||||
* <p> 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.
|
||||
*
|
||||
* <p> 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.
|
||||
*
|
||||
* <a id="MemoryConsistency"></a>
|
||||
* <h2>Memory Consistency Properties</h2>
|
||||
* Certain interactions between references, reference queues, and the garbage
|
||||
* collector form
|
||||
* <a href="{@docRoot}/java.base/java/util/concurrent/package-summary.html#MemoryVisibility"><i>happens-before</i></a>
|
||||
* relationships:
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li>Actions in a thread prior to calling
|
||||
* {@link Reference#reachabilityFence Reference.reachabilityFence(x)}
|
||||
* <i>happen-before</i> the garbage collector clears any reference to {@code x}.</li>
|
||||
*
|
||||
* <li>The clearing of a reference by the garbage collector <i>happens-before</i>
|
||||
* the garbage collector enqueues the reference.</li>
|
||||
*
|
||||
* <li>The enqueueing of a reference (by the garbage collector, or
|
||||
* by a successful call to {@link Reference#enqueue}) <i>happens-before</i>
|
||||
* the reference is removed from the queue (<em>dequeued</em>).</li>
|
||||
*
|
||||
* <li>The dequeuing of a reference to a
|
||||
* {@linkplain Cleaner#register(Object object, Runnable action) registered}
|
||||
* object, by the Cleaner thread, <i>happens-before</i> the Cleaner thread runs
|
||||
* the cleaning action for that object.</li>
|
||||
*
|
||||
* </ul>
|
||||
* The above chain of <i>happens-before</i> edges ensures that actions in a
|
||||
* thread prior to a {@link Reference#reachabilityFence Reference.reachabilityFence(x)}
|
||||
* <i>happen-before</i> 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}.
|
||||
*
|
||||
* <p>
|
||||
* The interaction between references, finalizers, and the garbage collector
|
||||
* also forms a <em>happens-before</em> relationship:
|
||||
*
|
||||
* <ul>
|
||||
* <li>Actions in a thread prior to calling
|
||||
* {@link Reference#reachabilityFence Reference.reachabilityFence(x)}
|
||||
* <i>happen-before</i> the finalizer for {@code x} is run by a finalizer thread.</li>
|
||||
* </ul>
|
||||
*
|
||||
* This ensures that actions in a thread prior to a
|
||||
* {@link Reference#reachabilityFence Reference.reachabilityFence(x)}
|
||||
* <i>happen-before</i> 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
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue