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

Roger Riggs Roger.Riggs at Oracle.com
Mon Oct 5 22:11:14 UTC 2015


Building on Peter's code to provide subclassable CleanableReferences, I 
the implementation a bit to make it easier to maintain.
The CleanableReferences subclasses are nested inside the Cleaner to make 
the scoping clear.

Please review and comment:



Thanks, Roger

On 10/2/2015 11:34 AM, Roger Riggs wrote:
> Hi Peter,
> Great comments, thanks for  looking into this...
> On 10/2/2015 7:52 AM, Peter Levart wrote:
>> Hi Roger,
>> This is a nice and clean API. I like the trick with embedding a 
>> private CleanerImpl in Cleaner and registering Cleaner itself as a 
>> tracked object so that automatic thread termination can be performed 
>> in a safe manner. You say the scope of this is not to replace 
>> internal usages of sun.misc.Cleaner. But if they ever get replaced, 
>> there are two differences between the implementations to note:
>> - sun.misc.Cleaner thunks get executed by a ReferenceHandler thread 
>> directly and bypass ReferenceQueue-ing. This might be OK for internal 
>> use, but not appropriate for public API. I doubt this 
>> sun.misc.Cleaner exception in ReferenceHandler is necessary though.
>> - With sun.misc.Cleaner one has to create a minimum of 2 additional 
>> objects per tracked object: the Cleaner object and a Runnable thunk. 
>> This API requires creation of 3 objects per tracked object: the 
>> Cleanup object, the internal Reference object and a Runnable thunk.
>> Do you think Cleaner will not be used in scenarios where this 
>> additional footprint matters?
> I don't have any particular data on that point.  When used with lambda 
> or method references for
> the thunk, it is likely there will be some binding overhead.
>> It might be possible to merge the roles of Cleanup and Reference into 
>> one object, like this:
>> http://cr.openjdk.java.net/~plevart/jdk9-dev/Cleaner/Cleaner.java
>> Making Cleanup an interface, internal Reference(s) can implement it. 
>> One can cast a Cleanup instance to a Reference and invoke it's other 
>> methods, but this can be prevented by throwing 
>> UnsupportedOperationException from them, so nobody is tempted to 
>> employ this implementation detail.
> I prototyped a similar implementation but backed it out due to the 
> code duplication and complexity.
> It also seemed a poor choice to break the contract of Reference by 
> throwing UnsupportedOperationException
> on the unneeded but exposed methods since they could not be completely 
> encapsulated.
> It seemed cleaner to have only a concrete type that was exposed to the 
> clients.
> BTW, the code in you cleaner might be simpler if the cleaner lists for 
> each of the three types were separate.
> (The entries don't need to be intermixed).  That could simplify the 
> virtual next/prev access but would still be
> duplicating the linked list management code).
> There could be multiple insertXXX methods so the casts were not 
> necessary.
>> There might be utility in exposing Cleanup (or better named 
>> Cleanable) References as public abstract classes so that a footprint 
>> sensitive application (for example in a data structure with many 
>> elements) is possible. By subclassing such an abstract reference and 
>> implementing the abstract method, a single object is required per 
>> tracked object. Here I derived a proof of concept from your code:
>> http://cr.openjdk.java.net/~plevart/jdk9-dev/Cleaner/webrev.01/
>> The simple API is unchanged and there is additional low-level API 
>> that can be used if footprint matters.
>> What do you think?
> I see what you're getting at.  I would probably try to rearrange it so 
> that only the performMethod
> could be overridden.   Overriding clean() and clear() might disable 
> the list management
> and reduce the robustness.
> I'll take another look, I was most concerned with simplicity, but if 
> the overhead for the number
> of the objects is a concern that can be traded off against a more 
> complex implementation.
> Thanks, Roger
>> Regards, Peter
>> On 10/01/2015 04:12 PM, Roger Riggs wrote:
>>> Please review a proposal for public Cleaner API:
>>> A Cleaner is proposed to provide an easy to use alternative to 
>>> finalization. The service would provide easy registration and 
>>> cancellation of cleanup functions for objects. Applications create a 
>>> cleanup service for their own use and the service terminates when it 
>>> is no longer in use.
>>> Finalization has a long history of issues both in usage and 
>>> performance. PhantomReferences have been proposed as the alternative 
>>> GC based mechanism for cleaning functions but it has been left as an 
>>> exercise to the developer to construct the necessary mechanisms to 
>>> handle ReferenceQueues, handle threading issues and robust termination.
>>> The Cleaner performs cleaning functions when objects are unreachable 
>>> as found by garbage collection using the existing mechanisms of 
>>> PhantomReference, WeakReference, SoftReferences, and 
>>> ReferenceQueues. It manages a thread that dequeues references to 
>>> unreachable objects and invokes the corresponding cleaning function. 
>>> Registered cleaning functions can be cleared if no longer needed, 
>>> can be invoked explicitly to perform the cleanup immediately, or be 
>>> invoked when the object is not reachable (as detected by garbage 
>>> collection) and handled by a cleanup thread.
>>> The java.lang.ref package is proposed for the Cleaner because it is 
>>> complementary to the reference classes and reference queues and to 
>>> make it easy to find.
>>> It is not a goal to replace all uses of finalization or 
>>> sun.misc.Cleaner in the JDK.
>>> Investigation will evaluate if and in what cases the Cleaner can 
>>> replace finalization.
>>> A subsequent task will examine uses of finalization and propose 
>>> specific changes
>>> on a case by base basis.
>>> Please review and comment:
>>> Javadoc:
>>>   http://cr.openjdk.java.net/~rriggs/cleaner-doc/
>>> Webrev:
>>>    http://cr.openjdk.java.net/~rriggs/webrev-cleaner-8138696/
>>> Issue:
>>>    https://bugs.openjdk.java.net/browse/JDK-8138696
>>> Thanks, Roger

More information about the core-libs-dev mailing list