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();
         }
     }
}

ublic 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 !!

Reference: http://howtodoinjava.com/2012/10/31/why-not-to-use-finalize-method-in-java/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值