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

Peter Levart peter.levart at gmail.com
Tue Oct 13 08:31:05 UTC 2015


Hi Roger, Mark and Mandy

On 10/13/2015 03:12 AM, Mandy Chung wrote:
>> On Oct 12, 2015, at 12:30 PM, mark.reinhold at oracle.com wrote:
>>
>> 2015/10/8 1:41 -0700, roger.riggs at oracle.com:
>>> Webrev:
>>> http://cr.openjdk.java.net/~rriggs/webrev-cleaner-extensible-8138696/
>>>
>>> javadoc:
>>>     http://cr.openjdk.java.net/~rriggs/cleaner-doc2/
>> Roger -- thanks for taking this on.  The more we can do to get people
>> to stop using sun.misc APIs, the better.
>>
>> A couple of comments/questions:
>>
>> First, I think the approach in your first version is, well, cleaner.
> +1
>
> I started reviewing the first version and pondering on the benefits of the new versions.
>
>
>> The additional abstract classes in the second version look like a
>> classic case of implementation inheritance that's not subtype
>> inheritance, what with the overrides of the original enqueue and
>> isEnqueued methods to throw UnsupportedOperationException.
>>
>> I understand the desire to avoid allocating too many objects, but
>> do we have actual use cases where that's critical?  The original
>> sun.misc.Cleaner has been used by both internal and external code
>> to do relatively heavy-weight things like unmap direct buffers and
>> release other kinds of native resources, which suggests that
>> allocating three small objects per cleaner is not a problem.
>>
>> Second, the original sun.misc.Cleaner only handles phantom references.
>> What are the use cases for weak and soft cleaners?
>>
>> Finally, how important is it to be able to unregister a cleaner?  In
>> all the years we've had sun.misc.Cleaner that capability has never
>> been needed, and leaving it out would simplify the API.
> If there is no strong need of unregister a cleaner, Cleaner API won’t need to return a Cleanable object which I think it’s nice and simpler.
>
> Mandy
>

There is one usage of sun.misc.Cleaner.clean() in JavaFX, I think. I 
also think that this API could have two faces: the simple face (it might 
even be without returning Cleanable and only Phantom-typed to be 
super-simple). The other low-level face could be abstract 
[Phantom|Weak|Soft]CleanableReference(s) which would take a mandatory 
Cleaner instance in the constructors instead of a ReferenceQueue. There 
could also be a JDK-internal single instance of a permanent Cleaner with 
a background thread to be used for JDK-internal cleanup tasks. I think 
there are several opportunities for the low-level part of the API in the 
JDK:

- ClassLoader.getClassLoadingLock(String className): maintains an 
internal ConcurrentHashMap<String, Object> for locks - one entry per 
class-loading attempt. Those locks are just used briefly in most 
occasions and then kept in the map indefinitely. A couple of years ago I 
did an experiment to replace such map with ConcurrentHashMap<String, 
WeakReference<Object>> and it observably reduced the final footprint 
after starting-up an application with lots of classes. The 
sub-optimality of that approach was that some locks were always kept 
alive, since the expunging of cleared WeakReferences from the map was 
performed by class-loading requests and there can be long periods in an 
application without class-loading activity. An "active" auto-cleanable 
WeakReference would off-load the expunging activity to a background 
thread which would make sure to remove *all* cleared references from the 
map.

- A couple of months ago I did a successful experiment in refactoring 
File[Input|Output]Stream and RandomAccessFile to use a Cleaner-like API 
instead of finalize() method. It was based on the premise that there is 
an on-demand cleaning method like Cleaner.clean(), which was called as 
part of the last close() on the FileHandle.

[Phantom|Weak|Soft]Reference(s) are not something an average application 
programmer uses every day. It's more for constructors of middle-ware I 
think. And those are the programmers that are not afraid of lower-level 
APIs. They do care for flexibility of the API.

But if the low-level API is not something that you are comfortable to 
expose to users, could it at least be used internally? Simply moving the 
public [Phantom|Weak|Soft]CleanableReference(s) to an internal package 
(like java.lang.ref.internal)?

Regards, Peter




More information about the core-libs-dev mailing list