RFR 9: 8138696 : java.lang.ref.Cleaner - an easy to use alternative to finalization

David M. Lloyd david.lloyd at redhat.com
Tue Dec 8 15:50:16 UTC 2015


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



More information about the core-libs-dev mailing list