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

Peter Levart peter.levart at gmail.com
Tue Dec 8 19:26:17 UTC 2015



On 12/08/2015 07:25 PM, Kim Barrett wrote:
> On Dec 8, 2015, at 3:09 AM, David Holmes <david.holmes at oracle.com> wrote:
>> Question: what happens if an object is registered simultaneously with multiple Cleaners? Do we need to warn the user against that?
> Aside: I like David's suggested "action" terminology.
>
>> Question: what happens if an object is registered simultaneously with
>> multiple Cleaners? Do we need to warn the user against that?
> Registering an object with multiple Cleaners, or even the same Cleaner
> multiple times, is not a problem, so long as the various cleanup
> actions can cope with that.  This is even expected to occur in
> practice.  Consider the conversion of a class hierarchy away from
> using finalize() to instead using Cleaners.  A base class may register
> a cleanup action for the state associated with that (base) class.  A
> derived class may independently register a cleanup action for the
> additional state associated with that derived class.  The derived
> class's cleanup action might be registered with the same or a
> different Cleaner than that used by the base class.
>

One thing to note is that independent actions registered on the same 
referent may execute in arbitrary order (each registration is a separate 
PhantomReference). If order is important then something like the 
following will be required:


public class BasicClass implements AutoCloseable {

     protected static class BasicState implements Runnable {
         @Override
         public void run() {
             // cleanup actions that access 'BasicState'
         }
     }

     protected BasicState createState() {
         return new BasicState();
     }

     private final BasicState state = createState();

     private final Cleaner.Cleanable cleanable =
         Cleaner.commonCleaner().register(this, state);

     @Override
     public void close() throws Exception {
         cleanable.clean();
     }
}


public class DerivedClass extends BasicClass {

     protected static class DerivedState extends BasicState {
         @Override
         public void run() {
             super.run(); // BasicState cleanup...
             // DerivedState cleanup...
         }
     }

     @Override
     protected BasicState createState() {
         return new DerivedState();
     }
}


...this is not so simple as with finalize() any more, but doable.


It's unfortunate that the "more complicated" PhantomCleanable API did 
not make it as it would not be much more complicated for such scenarios:


public class BasicClass implements AutoCloseable {

     protected static class BasicCleanableState extends 
CleanerImpl.PhantomCleanable<BasicClass> {

         public BasicCleanableState(BasicClass referent, Cleaner cleaner) {
             super(referent, cleaner);
         }

         @Override
         protected void performCleanup() {
             // cleanup actions that access 'BasicCleanableState'
         }
     }

     protected BasicCleanableState createState(Cleaner cleaner) {
         return new BasicCleanableState(this, cleaner);
     }

     private final BasicCleanableState cleanableState = 
createState(Cleaner.commonCleaner());

     @Override
     public void close() throws Exception {
         cleanableState.clean();
     }
}


public class DerivedClass extends BasicClass {

     protected static class DerivedCleanableState extends 
BasicCleanableState {

         public DerivedCleanableState(BasicClass referent, Cleaner 
cleaner) {
             super(referent, cleaner);
         }

         @Override
         protected void performCleanup() {
             super.performCleanup(); // BasicCleanableState cleanup
             // DerivedCleanableState cleanup
         }
     }

     @Override
     protected BasicCleanableState createState(Cleaner cleaner) {
         return new DerivedCleanableState(this, cleaner);
     }
}


Regards, Peter




More information about the core-libs-dev mailing list