Sunday, 12 August 2012

Java Finalize Method: When and How to Implement It?

When an object becomes unreachable, it is flagged as collected by the garbage collector. If it has a finalize() method, it is marked for finalization and put in a finalization queue. After finalization, it becomes finalized. If it does not have a finalize() method, it is directly marked as finalized without being inserted in the finalization queue.

The finalization queue is subject to memory limitations like the application itself. One cannot precisely guess when or how often the content of the finalization queue will be processed, though the lower the remaining amount of memory, the higher the probability this process will happen 'soon'.

Once an object has been finalized, it is ready for deallocation. Java guarantees that finalize() is never called more than once on an object. If there is no more hard reference to this object after finalization, then the memory used for this object is released. In other words, finalization does not guarantee memory recollection.

Do's

  • Do call the super implementation of finalize() - If you implement a finalize() method in an object, make sure this method calls finalize() on the super object (i.e. super.finalize()).
  • Double-check that resources have been released - Let's assume an object is referencing a file or any other non memory resource. It is considered a safe practice to double-check that such resource and been closed and released properly in a finalize() method.

Don't

  • Don't do the job of the garbage collector - Let's assume an object has a list (for example). Do not implement a finalize() method to clear the list of its elements in order to free memory. It is an unnecessary overhead. The garbage collector will do this for you very efficiently and automatically.
  • Do not wait for finalize() to release resources - Assuming resource object A has a reference to resource B, and object B has a reference to A. Assuming both A and B wait until the call of finalize() to release their reference to each other. This may never happen, especially if there is a static final reference to A or B elsewhere in the application. Resources should be released explicitly as soon as they are not required by the application anymore. Don't wait for a call to finalize().
  • The call order of finalize() methods is unpredictable - Don't make any assumptions about the call order of finalize() methods.
  • Don't create a hard reference to a finalized object - The finalize() method is called when an object has become unreachable. Do not create a hard reference, for example by adding it to a list in another object, because this will prevent its memory recollection.
If you are implementing a mechanism monitoring the memory usage of your application, you may call System.runFinalization() to facilitate the deallocation process and memory recollection (if necessary).