Hi Hans,
On 3/31/2017 2:56 PM, Hans Boehm wrote:
Agree entirely with Andrew's concern. I would mostly point to the
java.lang.Reference documentation. One possible approach follows.
Add the following to the apiNote. I would add it at the beginning,
since I've rarely encountered the inheritance issues, and they're
probably easier to debug:
As with all reachability-based cleanup mechanisms, it is important to
use java.lang.reReference.reachabilityFence to ensure that objects
remain reachable while resources embedded in the object are in use.
Good suggestion for the Object.finalize deprecation doc, I'll see how to
work that in.
However, looking at the reachabilityFence documentation, I think it's
quite misleading, and greatly understates the need for using it. In
particular the following paragraph seems most misleading:
"This method is designed for use in uncommon situations of premature
finalization where using 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 12.6 17 of The Java™ Language Specification)
that are implemented in ways that rely on ordering control for
correctness."
These seem completely misleading to me.
I would replace this with
This method should be used when cleanup actions (finalize() calls, or
Reference enqueuing, Cleaner invocation) could otherwise be triggered
while a resource under control of the object is still in use. This
method should normally be called when these cleanup facilities are
used to perform actions other than simply issuing a warning.
(Specific complaints about the original: In my experience, this is
needed for the large majority of finalization/ReferenceQueue uses.
What's the point of a finalizer without visible effects? The object is
otherwise dead: Why bother? In practice, synchronization almost never
provides the correct guarantees. Finalizers should indeed usually
synchronize, but NOT on the object itself. It's not clear what
"ordering control" here means. The order in which program actions are
performed generally does matter.)
The section starting with "It is sometimes possible to better
encapsulate use of reachabilityFence..." just seems misleading. Delete
it. I can't imagine a scenario in which that could work. Using files
as a (bad for other reasons) example, assume the external resource is
a file descriptor, and I'm about to read it. Keeping the file open
until I retrieve the descriptor isn't good enough. It needs to be kept
open for the duration of the read.
I would replace the last paragraph with the following, or delete it
entirely. I don't believe I've ever seen code to which it applies:
ReachabilityFence is not needed when all uses of the embedded resource
(including in the constructors or the finalize() method) are entirely
enclosed in synchronized(this) blocks.
(Note again that surrounding all accesses to the object itself in
synchronized blocks does not suffice.)
Right, good suggestions.
Though I think that's out of scope for the current deprecation issue.
I created a new Issue [1] to track that and reference that/this email.
Thanks, Roger
[1] 8177915 Clarify Reference.reachabilityFence use
<https://bugs.openjdk.java.net/browse/JDK-8177915>