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