Friday, July 23, 2021

10 points on finalize method in Java – Tutorial Example

finalize method in java is a special method much like the main method in java. finalize() is called before the Garbage collector reclaims the Object, its last chance for any object to perform cleanup activity i.e. releasing any system resources held, closing the connection if open etc. The main issue with finalize() method in Java is it's not guaranteed by JLS that it will be called by Garbage collector or exactly when it will be called, for example, an object may wait indefinitely after becoming eligible for garbage collection and before its finalize() method gets called. similarly even after finalize gets called it's not guaranteed it will be immediately collected.

Because of the above reason, it makes no sense to finalize the method for releasing critical resources or perform any time-critical activity inside finalize. It may work in development in one JVM but may not work in another JVM.

In this Java tutorial, we will see some important points about the finalize method in Java, How to use the finalize method, what to do, and what not to do inside finalize in Java.  Btw, the best advice on finalize method is given by none other than Joshua Bloch in his timeless classic book, Effective Java. Don't forget to read that after reading this article.

And, If you are new to Java then you can also check out these Java Programming online courses from Coursera, Udemy, and Codecademy, and other online portals. This is one of the best and up-to-date resources to learn Java online.


What is finalize method in Java – Tutorial Example

1) finalize() method is defined in java.lang.Object class, which means it is available to all the classes for the sake of overriding. finalize method is defined as protected which leads to a popular core java question "Why is finalize is declared protected instead of the public"? 

well, I don't know the exact reason its falls in the same category of questions like why java doesn't support multiple inheritances which can only be answered accurately by designers of Java. any way making finalize protected looks good in terms of following rule of encapsulation which starts with least restrictive access modifier like private but making finalize private prevents it from being overridden in the subclass as you can not override private methods, so making it protected is next obvious choice.



2) One of the most important points of finalize method is that it's not automatically chained like constructors. If you are overriding finalize method then it's your responsibility to call finalize() method of the superclass, if you forgot to call then finalize of super class will never be called. so it becomes critical to remember this and provide an opportunity to finalize of super class to perform the cleanup. 

The best way to call superclass finalize method is to call them in the finally block as shown in the below example. This will guarantee that finalize of the parent class will be called in all conditions except when JVM exits:

 @Override
    protected void finalize() throws Throwable {
        try{
            System.out.println("Finalize of Sub Class");
            //release resources, perform cleanup ;
        }catch(Throwable t){
            throw t;
        }finally{
            System.out.println("Calling finalize of Super Class");
            super.finalize();
        }
     
    }


3) finalize method is called by garbage collection thread before collecting object and if not intended to be called like a normal method.


4) finalize gets called only once by GC thread if the object revives itself from the finalize() method then finalize will not be called again.


5) Any Exception is thrown by finalize method is ignored by GC thread and it will not be propagated further, in fact, I doubt if you find any trace of it.


6) There is one way to increase the probability of running of finalize method by calling System.runFinalization() and
Runtime.getRuntime().runFinalization(). These methods put more effort that JVM call finalize() method of all object which are eligible for garbage collection and whose finalize has not yet called. It's not guaranteed, but JVM tries its best.


Alternative of finalize method for cleanup

So far its seems we are suggesting not to use finalize method because of its non-guaranteed behavior but than what is alternative of releasing resource, performing cleanup because there is no destructor in Java. Having a method like close() or destroy() make much sense for releasing resources held by classes. 

In fact, JDK library follows this. if you look at java.io package which is a great example of acquiring system resources like file descriptor for an opening file, offers close() method for opening stream and close() for closing it. In fact its one of the best practices to call the close method from the finally block in java. 

The only caveat with this approach is it's not automatic, the client has to do the cleanup and if client forgot to do the cleanup there are chances of resources getting leaked, which again suggests us that we could probably give another chance to finalize method. You will be pleased to know that Java 7 has added an automatic resource management feature that takes care of closing all resource opened inside try block automatically, leaving no chance of manual release and leakage.



When to use finalize method in Java?

In the last paragraph, I pointed out that there are certain cases where overriding finalize makes sense like an ultimate last attempt to clean up the resource. If a Java class is made to held resources like input-output devices, JDBC connection then you should override finalize and call its close() method from finalizing. though there is no guarantee that it will run and release the resource in a timely best part is we are not relying on it. 

It is just another last attempt to release the resource which most likely has been already released due to the client calling the close() method. This technique is heavily used inside the Java Development library. look at the below example of finalize method from FileInputStream.java

protected void finalize() throws IOException {
        if ((fd != null) &&  (fd != FileDescriptor.in)) {

            /*
             * Finalize should not release the FileDescriptor if another
             * stream is still using it. If the user directly invokes
             * close() then the FileDescriptor is also released.
             */
            runningFinalize.set(Boolean.TRUE);
            try {
                close();
            } finally {
                runningFinalize.set(Boolean.FALSE);
            }
        }

    }



What not to do in finalize method in Java

trusting finalize method for releasing critical resources is the biggest mistake java programmer can make. suppose instead of relying on the close() method to release file descriptor, you rely on finalizing to relapse it for you. 

Since there is no guarantee when finalize method will run you could effectively lock hundreds of file-descriptor of earlier opened files or sockets and there is a high chance that your application will run out of file-descriptor and not be able to open any new file

It's best to use finalize as the last attempt to do cleanup but never use finalize as a first or only attempt.


How finalize() works in Java



That's all on finalize method in Java. as you have seen there are quite a lot of specifics about finalizing method which java programmers should remember before using finalize in java. In one line, don’t do the time-critical tasks on finalize method but use finalize with caution.


Related Java Articles and Tutorials
  • How SubString method works internally in Java? (answer)
  • How to parse XML files in Java using DOM parser? (solution)
  • How to convert Enum to String in Java with Example? (program)
  • 10 best practices to follow while writing code comments in Programming? (tips)
  • 10 Object-oriented design principles Java programmers should know? (article)
  • 10 JVM options Java developers should know. (read more)
  • How to avoid deadlock in Java – Code Example (answer)

Bonus point
It's extremely rare to override Objects.finalize() method. It's not advised to override it but if you have to then first read and understand Effective Java, Item 7, "Avoid Finalizers", very carefully, and then don't do it. 


14 comments:

  1. I was looking information on how to call finalize method in java as I knew finalize is not chained like constructor. that seems buggy to me. anyway never knew this much information on java finalize method, thanks .

    ReplyDelete
  2. very informative post.. to learn other languages the tutorials available at http://goforexam.blogspot.com

    ReplyDelete
  3. but can finalize method be overloaded?????

    ReplyDelete
  4. Actually there is an alternative mechanism in Java, but it is cumbersome to implement and quite difficult to do correctly.
    The PhantomReference is positioned by Java as the preferred alternative to finalizers. It also solves some other issues on finalizers as from which context (thread).

    ReplyDelete
  5. Why finalize is declared protected instead of public? because it will only be called by JVM. it is protected, as the class use it, they will override it .

    ReplyDelete
  6. Hi,

    If if an object made reference during finalize() will that object get garbage collected or not ?

    ReplyDelete
  7. why finailize method is decalred as protected, the rest of the method in the object class are declared as public

    ReplyDelete
  8. @RajKumar, even clone() method is declared as protected.

    ReplyDelete
  9. What's difference between finalize() method and System.gc() method ?

    ReplyDelete
  10. Hi, point 6 is very misleading-- "There is one way you can guarantee running of finalize method by calling System.runFinalization()". There seems no way to guarantee running of this method. I just tried it in a program, it doesn't run.
    The Oracle reference doc too reads- "Calling this method suggests that the Java Virtual Machine expend effort toward running the finalize methods of objects that have been found to be discarded but whose finalize methods have not yet been run. When control returns from the method call, the Java Virtual Machine has made a best effort to complete all outstanding finalizations."
    But Your blog is very good, and highly informative. Please modify the 6th point if you get sometime.

    ReplyDelete
  11. @Shantinath, you are right, finalization is not guaranteed, it always work on best effort basis. Thanks for pointing it out, corrected now

    ReplyDelete
  12. @Javin: So humble of you to acknowledge it. You are doing great work writing these articles. These java articles on your blog are clearing Java doubts in such a simple, exemplary and conceptual way, which I am sure none other website would be doing. Your blog is really a great help for Java folks looking around to learn more, and for people appearing in interviews. Keep up the great work.

    ReplyDelete
  13. Very useful article. Talking about your first point, I think the next restrictive access modifier to 'Private' is 'Default' and not 'Protected'. Please let correct me if I'm wrong.

    ReplyDelete