Java finalize()
Java finalize()
In Java, the Object class is the root class that is inherited by all the Java classes. The class provides the finalize() method that is called just before the deletion or destroying the object (which is eligible for garbage collection). It is called by the garbage collector when there are no more references to object. It removes the unused objects in order to free up theheap memory. In short, we can say thatit is used to perform cleanup activity.
Syntax:
protected void finalize() throws Throwable { }
How garbage collector uses finalize() method?
The garbage collector calls finalize() method, when an object is dereferenced. The dereferenced object need to be destroyed by the garbage collector.
Consider the example, a class named Employee is declared having an object named emp.
public class Employee { //statements Employee emp = new Employee(); emp = null; }
The object emp is first declared and has a reference to the Employee class.In the next statement, we have assigned null value to the object emp. It means no reference at all. So,the garbage collector marks it as garbage.Now, the garbage collector invokes thefinalize() method to destroy the object.
Overriding finalize() Method
The following code snippet shows how to override the finalize method in a class named Sample.
Samle.java
public class Sample { //overriding finalize() method @Override protected void finalize() throws Throwable { try { System.out.println("Inside the finalize method"); } catch(Throwable e) { throw e; } finally { //invokes the finalize() method of the Object class super.finalize(); } } //driver code public static void main(String a[]) throws Throwable { Sample s = new Sample(); //invokes the Sample class finalize method s.finalize(); } }
Output:
Inside the finalize method
We can also call the finalize() method explicitly. Let’s understand it through a Java program.
Callingfinalize() method Explicitly
When finalize() method is called explicitly, the JVM executes it as normal method. The JVM will not be able to remove or destroy the object from memory. The explicit method call can only work with garbage collector to release memory.
Sample.java
public class Sample { public static void main(String a[]) { Sample s1 = new Sample(); Sample s2 = new Sample(); s2 = null; // Explicit call s1.finalize(); System.out.println("Garbage collector"); System.gc(); //Implicit call to finilize() method } @Override protected void finalize() { System.out.println("finilize() method called"); } }
Output:
finilize() method called Garbage collector finilize() method called
In the above code snippet, no object is destroyed when finalize() method is called. But when the gc() method of the System class is invoked, it makes an implicit call to the finalize() method and removes the s2 object from memory.
Drawbacks of Usingfinalize()Method
- During the program execution there is no specific time allocated for garbage collection. It can execute at any time evenin between of the program execution. It also affects the performance ofthe system and system might run out of resources, as it has limited resources.
- As the garbage collection is based on JVM, a program may run without any errors on one system but might face problems on another.
- An exception thrown by the finalize() method is not handled by garbage collector. Additionally, it will also be not logged in the log files.
- There is a possibility that it may delete live objects that are being used further inside the same program.
Alternativeoffinalize() Method
Considering the drawbacks offinalize() method, the following alternative can be used instead of using finalize() method.
Using Cleaner class
We can use the Java Cleaner class to perform the functionality of dereference of an object. Java Cleaner class is presented since Java 9. It belongs to java.lang.ref.When an object is dereferenced, an alert is sent to the Cleaner class object. The object is then registered with the Cleaner class object using the register() method.
CleanerSample.java
import java.lang.ref.Cleaner; public class CleanerSample { public static void main(String a[]) { System.out.println("Start CleanerSample..."); Cleaner cleaner = Cleaner.create(); CleanerSample obj = new CleanerSample(); //register cleaner cleaner.register(obj, new CleanerSampleRunnable()); for (int i = 1; i<= 100000; i++) { String[] s1 = new String[1000]; try { Thread.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("Execution Finished..."); } private static class CleanerSampleRunnable implements Runnable { public void run() { System.out.println("CleanerSample cleaning action executed..."); } } }
In the above code, the object objis registered with the Cleaner class. So, the runnable instance CleanerSampleRunnable gets executed after the object CleanerSampleRunnableis destroyed.
Output:
Start CleanerSample... CleanerSample cleaning action executed... Execution Finished...
In this way, we have understood the concept of finalize() method in Java, its drawbacks and where and when to use finalize() method with the help of Java programs.