JDK-8138696 : java.lang.ref.Cleaner - an alternative to finalization
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2015-10-01
  • Updated: 2022-08-03
  • Resolved: 2015-12-21
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9 b99Fixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
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.

It is not a goal to replace all uses of finalization or sun.misc.Cleaner.  Investigation will evaluate if and in what cases the cleaner can replace finalization.

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.
Comments
URL: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/7c8488605485 User: lana Date: 2015-12-23 23:04:19 +0000
23-12-2015

I planned to add a common cleaner with the first batch of finalizer changes but the common cleaner can be added sooner. What I had in mind is in this prototype webrev: http://cr.openjdk.java.net/~rriggs/webrev-cleaning-finalizers/src/java.base/share/classes/jdk/internal/misc/CleanerFactory.java.html If you are ready for that, we can do it sooner.
22-12-2015

[~rriggs] now that this API is in the JDK, can we create a single Cleaner for the base module ( or possibly the platform itself )? Id like to move the nio usages of sun.misc.Cleaner and on to the new API.
22-12-2015

URL: http://hg.openjdk.java.net/jdk9/dev/jdk/rev/7c8488605485 User: rriggs Date: 2015-12-21 16:45:40 +0000
21-12-2015

Other similar mechanisms currently in use: sun.java2d.Disposer com.sun.prism.impl.Disposer com.sun.javafx.font,Disposer java.com.sun.webkit.Disposer.java
15-12-2015

I'd like to point out again (as in JDK-8051843) that making it possible for "client code callbacks (to happen) on the finalizer thread ... (has) no increased security/stability risks" compared to current JDK situation.
07-12-2015

@Martin, I suggest you post your comment to core-libs-dev in the review thread where the discussion should happen.
04-12-2015

In fact, I do have some similiar consideration of what Martin suggests when I reviewed the version of public SoftCleanable, WeakCleanable, PhantomReference. Reference(T referent, Runnable cleanup) PhantomReference(T referent, Runnable cleanup) SoftReference(T referent, Runnable cleanup) WeakReference(T referent, Runnable cleanup) May not necessarily be in the constructor but this gives the idea to integrate closely with references and reference queue. I think it is worth experimenting. I agree that some applications would want to avoid having one extra thread for each cleaner. I suggested to consider having a common cleaner for applications to use. As Roger noted, he considers as future work. Perhaps the static Cleaner.create() factory method should not specify a new thread such that that can be changed in the future. Overloading the FinalizerThread may not be a good idea though. The ability to specify its own thread (factory) for cleaning will give the opportunity for user code for performance or sharing of their own thread pool.
04-12-2015

We could still have some method that takes ThreadFactory for applications that want to reused their thread pool, or which find it convenient to have the callback on some known thread. But I'd prefer to have some single default for applications that do not care. Otherwise, as the usage of Cleaner grows, the number of associated threads can grow as well. Especially, when the application uses many libraries, which are not aware of each other and need to use the Cleaner. I proposed to overload the constructor, because it makes no sense to specify ReferenceQueue when we register the cleanup callback. But it may also be a method on Reference, e.g.: Reference.setCleanup(Runnable cleanup) Reference.setCleanup(Runnable cleanup, ThreadFactory threadFactory) where references with identical thread factories can share one of the factory's thread. setCleanup(null) could unregister the cleanup and Reference.clear() can call the cleanup and unregister. That way we'd have access to the reference itself and can use it as a key to e.g. an "active" implementation of WeakHashMap, that would release it's entries on the cleanup call.
04-12-2015

A conservative and simpler approach was recommended strongly for the public api requiring long term support. The implementation is structured as suggested using subclasses of Reference so that only a single object is created for each Cleanable. Though the client typically creates an object to maintain the state needed to invoke the cleaning function. If using Lambdas, the lambda creates the necessary binding and optimizes. Internal to the JDK java.base module the subclasses are available to be extended. for example, in the WeakHashMap implementation. Each Cleaner uses a dedicated thread to make it possible to use different Cleaners for different purposes and ensure non-interference between the cleaning functions. An application is encouraged to create a Cleaner and use it throughout the library or client code. Future work includes replacing use of finalization within the base module and a common Cleaner should be used.
04-12-2015

I went through the proposed implementation and I'm disappointed by the lack of features from JDK-8051843. There is a lack of one shared queue; an extra daemon thread is created for each client of Cleaner API. There is a lot of objects created with each registration. Some implementations will also duplicate references - one used by the client code and one created by Cleaner itself. One possible use-case of runnable call backs can be an implementation of WeakHashMap, which would release it's entries automatically. In NetBeans we use the NetBean's ActiveQueue to implement the active version of WeakHashMap, but it would be problematic to reimplement it with the proposed Cleaner API. I have a suggestion: Wouldn't is be much simpler and more flexible, if we introduce new constructors: Reference(T referent, Runnable cleanup) PhantomReference(T referent, Runnable cleanup) SoftReference(T referent, Runnable cleanup) WeakReference(T referent, Runnable cleanup) Reference would get new field private final Runnable cleanup; and Reference.tryHandlePending() would dispatch the cleanup.run() call to a single thread to process (maybe the FinalizerThread could be reused)? Any thoughts on this?
04-12-2015

Review thread on core-libs: http://mail.openjdk.java.net/pipermail/core-libs-dev/2015-October/035548.html
01-10-2015