Search code examples
javadestructorfinalizer

Check that a method is called before object is collected


I have an object that user typically creates using my factory. I want to make sure my user calls object.undo() before they throw it into the garbage collector.

This class setups the necessary resources so the user isn't writing to production services and instead use test specific services. The user needs to call undo to revert their override.

Here is what I want the user to do

// in setup()
FooObject object = FooFactory.overrideProductionServicesToTestServices();

// do your testing in test*()

// in tearDown()
object.undo()

Here is what the user end up doing

// in setup()
FooFactory.overrideProductionServicesToTestServices()

// do their testing. Everything works.

// Another test, everything breaks

How do I notify the user either via throwing an exception or via class design that the user should call undo()?


Solution

  • Instead of using a finalizer, which carries a performance impact alongside being rather easy to get wrong, why not store a PhantomReference to the created object inside the factory?

    From the Javadocs:

    Phantom references are most often used for scheduling pre-mortem cleanup actions in a more flexible way than is possible with the Java finalization mechanism.

    You could have the factory track the associated ReferenceQueue for that reference, and once the object is enqueued, perform the cleanup actions ordinarily done by undo.