Saturday 22 November 2008

Item 7: - Avoid Finalizers

This item could have been written to put me straight. I'm the C++ programmer it speaks about and I was desperate for finalizers to be Java's destructor. They aren't. In fact, unlike C++'s destructors they are unpredictable, often dangerous and generally unnecessary. Ok, so if you're not careful with exceptions destructors in the C++ can be dangerous too. Java finalizers are worse.

The item explains that you should never do anything time critical in finalizers as the JVM is "tardy" at running them. I did some experiments closing database connections in finalizers and could generate any evidence that they were called at all. If and when finalizers are called is JVM implementation specific. So cross platform programming using finalizers is unpredictable at best, disastrous at worst.

The item also explains that uncaught exceptions thrown in finalizers are ignored, but the finalization of the object is terminates leaving it in an unknown and potentially corrupt state, which can result in arbitrary nondeterministic behavior. Using finalizers also increases the time to terminate an abject a whopping 430 times according to an (unexplained) test example run by the author.

The item describes the alternative to using finalizers as providing an explicit termination method that can, typically, be called from a finally block. This is what I do in a lot of cases and what the Java database objects provide.

Finalizers could be used as a safety net for forgotten terminate method invocations on the basis that it's better to release resource late than never, but of course there's no guarantee it'll get released at all. Finalisers can also be used for "native peers" as long as they do not hold resources that need to be released.

The item finishes by explaining that finalizers are not chained in class hierarchies and therefore subclasses must call super class finalilizers explicitly and the guardian finalizer idiom.

I don't think there's much to argue with here. I also feel that Java would benefit from some sort cleanup mechanism, such as IDispose in C# or even C++ destructors.

Paul Grenyer

No comments: