Summary
The java.lang.ref
package and its classes should specify memory visibility properties.
Problem
Among the optimizations the JVM can make when running code, it can determine that an object can become unreachable even if a method on that object is still executing.
For classes that cleanup using Cleaner
or finalizer, this phenomenon can lead to unexpected cleanup because Cleaner
and finalizer perform cleanup on their own threads.
An example excerpt:
Resource resource = ...;
protected void finalize() { resource.close(); }
public void doSomething() {
Resource r = this.resource;
// At this point, 'this' is no longer required.
// It can be collected, and the finalizer run,
// closing the resource.
tryToUse(r); // use already-cleaned resource
}
One can protect against this by using Reference.reachabilityFence()
:
public void doSomething() {
try {
Resource r = this.resource;
tryToUse(r);
} finally {
Reference.reachabilityFence(this);
}
}
(This technique has fixed actual bugs, e.g. 8311902 : "Concurrency regression in the PBKDF2 key impl of SunJCE provider".)
Cleanup threads are also subject to Java memory model visibility rules. As such, if a resource is mutated on the main program thread, that mutation may not be seen on the cleanup thread (short of using synchronization actions, volatile variables, etc). This can potentially lead to incorrect cleanup.
However, the GC and relevant portions of the java.lang.ref
package (ReferenceQueue
, Reference.reachabilityFence()
) already operate in a way that includes sufficient happens-before edges between Reference.reachabilityFence()
and cleanup threads such that mutations occurring on a thread prior to reachabilityFence()
will be visible on the cleanup thread.
Thus, the recommended use of try-finally-reachabilityFence() protects against unexpected cleanup AND ensures memory visibility.
Solution
We would like to codify these memory visibility properties in the API spec. The following will be updated:
java.lang.ref
package-infojava.lang.ref.Reference
java.lang.ref.ReferenceQueue
java.lang.ref.Cleaner
Specification
The specdiff of the proposed API spec changes are attached. For convenience, the specdiff is also available here:
https://cr.openjdk.org/~bchristi/8314480/specdiff.10/overview-summary.html
and a build of the new JavaDoc is here:
https://cr.openjdk.org/~bchristi/8314480/javadoc.10/api/index.html
- csr of
-
JDK-8314480 Memory ordering spec updates in java.lang.ref
- Resolved