16

How does a "finalizer guardian" [Effective Java , page 30] work ?

Have you used them? Did it solve any specific problem ?

Vinoth Kumar C M
  • 10,378
  • 28
  • 89
  • 130

1 Answers1

20

It solves the problem of the sub-class forgetting to call the finalize method of the super-class. This pattern works by attaching an extra instance with overridden finalize to your super-class. This way, if the super-class goes out of scope, the attached instance would also go out of scope, which would trigger the execution of its finalize, which would in turn call the finalize of the enclosing class.

Here is a short snippet that showcases the guardian pattern in action:

public class Parent {

    public static void main(final String[] args) throws Exception {
        doIt();
        System.gc();
        Thread.sleep(5000); //  5 sec sleep
    }

    @SuppressWarnings("unused")
    private final Object guardian = new Object() {
        @Override protected void finalize() {
            doFinalize();
        }
    };

    private void doFinalize() {
        System.out.println("Finalize of class Parent");
    }

    public static void doIt() {
        Child c = new Child();
        System.out.println(c);
    }

}

class Child extends Parent {

    // Note, Child class does not call super.finalize() but the resources held by the
    // parent class will still get cleaned up, thanks to the guardian pattern
    @Override protected void finalize() {
        System.out.println("Finalize of class Child");
    }

}
Sanjay T. Sharma
  • 22,857
  • 4
  • 59
  • 71
  • 2
    But when the times come for the Parent class to be GC'ed , the parent class will not be able to be GC'ed since the anonymous class holds a reference to Parent class and the Parent class also holds a refrence to the anonymous class through the instance field link. So because of this circular reference how will the Parent and the anonymous class be eligible for garbage collection? – Geek Sep 26 '13 at 11:03
  • 2
    @Geek: Java has a pretty awesome GC which isn't tripped by circular references. More [here](http://stackoverflow.com/questions/1910194) – Sanjay T. Sharma Sep 26 '13 at 12:40
  • 1
    Should the `Parent.finalize()` call `Parent.doFinalize()`? Doesn't that result in `doFinalize()` getting called twice if the `Child` does call `super.finalize()` or if an instance of `Parent` is finalized? – Michael Anderson Jun 24 '14 at 02:12
  • @MichaelAnderson: +1; you are indeed correct in mentioning that the public class Parent shouldn't have a `finalize` method overridden. Edited. – Sanjay T. Sharma Jul 28 '14 at 19:25
  • @SanjayT.Sharma, Regarding "*Note, Child class does not call super.finalize()*", **yet** in the very first place, why would that even happen? Isn't it part of the contract for all child class finalizers to call `super` finalize ? – Pacerier Sep 17 '17 at 22:24
  • @Pacerier: Nope, it's not part of the contract (just another overridden method) and the sole reason for having the guardian pattern. It does not work like constructor chaining. – Sanjay T. Sharma Sep 18 '17 at 17:00