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][1] : "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-info
* `java.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
[1]: https://bugs.openjdk.org/browse/JDK-8311902