Hi Roger, Mark and Mandy
On 10/13/2015 03:12 AM, Mandy Chung wrote:
On Oct 12, 2015, at 12:30 PM, mark.reinh...@oracle.com wrote:
2015/10/8 1:41 -0700, roger.ri...@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