On 12/08/2015 07:41 AM, Peter Levart wrote:
(once again, for the list - I can't seem to hit the right button :-)

On 12/08/2015 01:51 PM, David M. Lloyd wrote:
Yeah I think that replacing finalize is a bad example.  With
Reference.reachabilityFence() around the corner, if you want finalize
you can (and should, I guess) just use finalize.

IMO Cleaners are better when you do not want the instance of an object
to be accessible at all before you clean it - because it corresponds
to mapped memory, a file descriptor, or some other native resource,
usually, and any invocation at all after it is cleaned would result in
Major Problems.  In this case you would put the FD, memory
address/size/etc. on the cleaner, so that the clean method can do the
cleanup.

Cleaners are also more efficient in that:

- they register cleanup actions manually from java code after the
referent is constructed. finalize() uses a call-back from VM into Java
to register a Finalizer on finalizable referent construction.

Interesting, I didn't know that. I always assumed that finalization used a reference queue.

- they can invoke and de-register cleanup actions prematurely by user
explicitly invoking Cleanable.clean() and therefore avoid being
processed by reference processing machinery (in the VM and in Java). For
example, FileInputStream, using this API instead of finalize(), would in
majority of cases invoke and de-register the cleanup prematurely as most
code makes sure it closes the file after use. finalize() OTOH has no
premature de-registration feature.

Yeah, I guess I see this argument, though in the native resource case you often want to take one action on close (like dup2 a dead FD into the FD slot, or change the state of mapped memory somehow) and a different action on GC (release the FD number or unmap memory). Otherwise you have to (somehow) synchronize all operations against the closed state (it's usually not enough to check it on method entry in such cases).

- with a fix for "8071507: (ref) Clear phantom reference as soft and
weak references do", the opportunity for GC to collect the referent in
the same phase as discovering it phantom-reachable opens up. Finalizer
OTOH keeps the referent reachable in order to invoke finalize() on it
and then clear()s the reference, delaying the collection of referent to
the next GC round.

True, but this comes back to the question: do I need "this" do perform the cleanup action, or not? If yes, finalize(), if no, cleaner/PhantomReference.

Also, one hopes that each framework/library/application would only
register one cleaner for its usages, rather than (say) one per class...

There was a debate about whether to provide a common cleaner instance:
Cleaner.commonCleaner() (like ForkJoinPool.commonPool()). It could be
created lazily, but then it would run forever...

No opinion on this.

--
- DML

Reply via email to