10 points on finalize method in Java – Tutorial Example (original) (raw)
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
- 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.
- 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();
}
}
finalize method is called by garbage collection thread before collecting object and if not intended to be called like a normal method.
finalize gets called only once by GC thread if the object revives itself from the finalize() method then finalize will not be called again.
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.
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.
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.