Why not to use finalize() method in java

We all know the basic statement that finalize() method is called by garbage collector thread before reclaiming the memory allocated to the object. In this post, we will drill down more deeply into this method.

Sections in this post:

  • finalize() execution is not guaranteed at all (with example)
  • Other reasons for not using it
  • finalize() add heavy penalty in performance
  • Guide for correct usage

finalize() execution is not guaranteed at all (with example)

Lets prove it using a program. I have written a simple java runnable with one print statement in each block i.e. try-catch-finally-finalize. I have also created another class which will create 3 instances of this runnable and then we will see the execution path.

public class TryCatchFinallyTest implements Runnable {

	private void testMethod() throws InterruptedException
	{
		try
		{
			System.out.println("In try block");
			throw new NullPointerException();
		}
		catch(NullPointerException npe)
		{
			System.out.println("In catch block");
		}
		finally
		{
			System.out.println("In finally block");
		}
	}

	@Override
	protected void finalize() throws Throwable {
		System.out.println("In finalize block");
		super.finalize();
	}

	@Override
	public void run() {
		try {
			testMethod();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
public class TestMain
{
	@SuppressWarnings("deprecation")
	public static void main(String[] args) {
	for(int i=1;i<=3;i++)
	{
		new Thread(new TryCatchFinallyTest()).start();
	}
	}
}

Output:

In try block
In catch block
In finally block
In try block
In catch block
In finally block
In try block
In catch block
In finally block

Amazing, finalize method has not executed at all for any thread. So this proves what I stated already. Reason which i can think of is: finalizers are executed by a separate thread from garbage collector. If JVM exits too early then garbage collector does not get enough time to create and execute finalizers. Please correct me if i am wrong??

Now, next question is, can we force it to execute?

Answer is yes. Yes, we can. Using Runtime.runFinalizersOnExit(true);

public class TestMain
{
	@SuppressWarnings("deprecation")
	public static void main(String[] args) {
		for(int i=1;i<=3;i++)
		{
			new Thread(new TryCatchFinallyTest()).start();
			Runtime.runFinalizersOnExit(true);
		}
	}
}

Output:

In try block
In catch block
In finally block
In try block
In try block
In catch block
In finally block
In catch block
In finally block
In finalize block
In finalize block
In finalize block

There is another method also: Runtime.getRuntime().runFinalization(); But, it only guarantees that GC will make best efforts. Even in our program it is not able to run finalize method for all 3 threads.

Moving forward, we have used Runtime.runFinalizersOnExit(true); Well, this is another pit. This method has already been deprecated in JDK, with following reason:

“This method is inherently unsafe. It may result in finalizers being called on live objects while other threads are concurrently manipulating those objects, resulting in erratic behavior or deadlock.”

So, in one way we can not guarantee the execution and in another way we the system in danger. Better, don’t use it.

Other reasons for not using it

1) finalize() methods do not work in chaining like constructors. It means like when you call a constructor then constructors of all super classes will be invokes implicitly. But, in case of finalize methods, this is not followed. Super class’s finalize() should be called explicitly.

Suppose, you created a class and wrote its finalize method with care. Someone comes and extend your class and does not call super.finalize() in subclass’s finalize() block, then super class’s finalize() will never be invoked anyhow.

2) Any Exception thrown by finalize method is ignored by GC thread and it will not be propagated further, in fact it will not be logged in your log files. So bad, isn’t it?

finalize() add heavy penalty in performance

In Effective java (2nd edition ) Joshua bloch says,

"Oh, and one more thing: there is a severe performance penalty for using finalizers. On my machine, the time
to create and destroy a simple object is about 5.6 ns.
Adding a finalizer increases the time to 2,400 ns. In other words, it is about 430 times slower to create and
destroy objects with finalizers."

I also tried above analysis on my system but i was not able to get that much difference. Although, there are some difference for sure. But that was around 30% on original time. On time critical systems, it is also a big difference.

Guide for correct usage

After all above arguments, if you still find a situation where using finalize() is essential, then cross check below points:

  • Always call super.finalize() in your finalize() method.
  • Do not put time critical application logic in finalize(), seeing its unpredictability.
  • Do not use Runtime.runFinalizersOnExit(true); as it can put your system in danger.
  • Try to follow below template for finalize method
@Override
protected void finalize() throws Throwable
{
	try{
		//release resources here
	}catch(Throwable t){
		throw t;
	}finally{
		super.finalize();
	}
}

I hope, i have added some more information on which you already knew. Please let me know of your thoughts.

Happy Learning !!

22 thoughts on “Why not to use finalize() method in java”

  1. Nice post and Great work lokesh sir, our post are really helpful for freshers and exp people…………..thanx please continue it

  2. nice article. I think finally construct is really required to release non memory resources in java & C#(C# Destructor will be translated in finalize() method by C# compiler). because it is not guarantee of the execution of finalize but finally clause will always execute so we can write code in finally to release non memory resources. C++ don’t require finally because when the object is destroyed the destructor will be called and we can write code to release non-memory resources in destructor. Correct me if i wrong.

  3. Dear Lokesh,
    If object become abandon or eligible for gc, then why gc will call finalize() method before sweeping that obj? what will do finalize() method once called by gc?

    1. GC will not call finalize. It’s responsibility of JVM. The idea behind finalizes is that application can perform some clean up before objects using that resource garbage collected and leave resource open without any use. If the object responsible for cleanup is garbage collected before even cleaning up resource, then it is against the desired use case.

      1. This is correct. Finalizing has nothing really to do with GC in an under-the-hood sense. Each object that overrides the Object finalize method will have a Finalizer object associated with it. This is a reference, and as such GC will not recognize the object as unreferenced and will not consider it for GC. Once it has been finalized then GC can clean it up as an unreferenced object.

  4. what happend if we didn’t call super.finalize method.without implementation of finalize method we should release non java resurces by using finally block.why should we implement finalize method.

    1. Best approach is that don;t use finalize(). Use finally instead to clean up resources in normal routine and attach shutdown hooks for application shutdown.
      If we didn’t call super.finalize method in child class, then it will not be invoked.

  5. For the record, the garbage collector is the one that is not guaranteed – this, in effect makes the finalize() method not guaranteed as well. Yes, even if you set the object to null. I would agree though that its not a good practice / recommendation to use the finalize() method to perform critical post-processing (closing DB connections or IO etc).

Note:- In comment box, please put your code inside [java] ... [/java] OR [xml] ... [/xml] tags otherwise it may not appear as intended.

Leave a Reply

Your email address will not be published. Required fields are marked *


− five = 2

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>