Hi Rick,

On 5/3/2017 10:21 PM, Rick Hillegas wrote:
Thanks, Roger. That is a helpful example.

Derby is a component which can be quiesced and unloaded on resource-constrained platforms, then re-loaded when resources free up. Unloading means garbage collecting all the classloaders created by the component so that, at the end, not a single scrap of Derby code remains loaded. Has the Cleaner pattern been tested under these kinds of conditions? Can you point me at a Cleaner-based library which successfully unloads and reloads itself without leaking classloaders?
The Cleaner thread will terminate when all of the cleaning actions have been cancelled or completed so it should not interfere with your goal of completely being unloaded. (Peter provided the design and implementation.) It will not retain any references to any object that is otherwise unreferenced.

The Cleaner is new enough (9 is not yet GA'd) that I don't know of any library using it. My example using sockets may be a bit misleading, since sockets will be closed when otherwise unreferenced (as are files). That was an example of placeholder for some kind of connection related state that needed to be cleaned up when the referencing object is unreferenced.

As Peter inquired, I would suggest investigating whether completely removing the finalization can have the desired effect. A server connection terminating unexpectedly would I think cause any server side transaction to cleanup as appropriate for the connection; and that's server side behavior.

Note also a difference between the finalize case and Cleaner. In the finalize case, there may be an entire graph of unreachable instances that are finalized together. The subgraph is unreachable from live roots but still has references between the disconnected graph objects. By contrast, the Cleaner is based on an object being unreachable and the object doing the cleaning is still reachable (perhaps only via the Cleaner mechanism). So the cleanup proceeds in layers with unreachable instances being reclaimed first and the cleanup instances being reclaimed, after they are invoked,
in a subsequent cycle.

Regards, Roger




Thanks,
-Rick


On 5/3/17 9:04 AM, Roger Riggs wrote:
Hi Rick,

The general nature of changes to use the Cleaner involve factoring out the cleanup code from the object being cleaned, though in many cases it does not require restructuring. For example, if an object holds a reference to a network socket that needs to be closed when the object is collected the socket.close() can called by the cleaner:

   Cleaner cleaner = ...;
   final Socket socket = ...;
   Object obj = ...;

   cleaner.register(obj, () -> {
   try {
   socket.close();
        } catch (IOException ioe) { // ignore}
   });


Creating a cleaner starts a thread that does the work so you'll want to decide
how to share it across the uses or to use than one.

Using lambdas for the cleaner functions is very lightweight but be careful to avoid the using bound variables in the lambda body because they implicitly retain a reference to the enclosing instance which will prevent the instance from becoming unreferences.

If there are more specific cases of interest let me know,

Regards, Roger


On 5/2/2017 10:08 PM, Rick Hillegas wrote:
When I compile Apache Derby using JDK 9 build 167, I see several instances of the following warning:

   warning: [deprecation] finalize() in Object has been deprecated

The javadoc for java.lang.Object.finalize() suggests that affected classes should migrate their finalization to a coding pattern based on the newly introduced java.lang.ref.Cleaner class. I am hesitant to try my hand at this without more guidance. Can you point me at a tutorial or list of best practices for implementing Cleaner-based finalization?

Thanks,
-Rick




Reply via email to