The finalize() method in Java is a member of the Object class and is called by the garbage collector before an object is destroyed to perform cleanup activities like releasing system resources or closing file streams. While it provides a mechanism for cleanup, its use is generally discouraged due to unpredictability in its execution timing and potential performance issues. Instead, it's recommended to use other resource management techniques like try-with-resources or explicit close methods for better reliability and control.
What is the Finalize Method in Java?
The finalize() method in Java is a protected method defined in the Object class, which is the superclass of all Java classes. It allows an object to perform any necessary cleanup operations before the garbage collector destroys it. When an object is no longer used or referenced, it becomes eligible for garbage collection. Before it is removed from memory, the garbage collector calls the finalize() method on the object. If the object has overridden the finalize() method, any custom cleanup code specified in that method will be executed.
To use the finalize() method in a class, you must override it with your implementation. In your implementation, you can include any necessary cleanup code, such as closing open files or releasing other resources.
However, there are some pitfalls to using the finalize() method. For example, it is not guaranteed to be called, and there is no way to know when it will be called. The finalize() method can also cause performance issues if it takes too long to execute.
Garbage Collector in Java
In Java, the Garbage Collector (GC) is a program that automatically manages the memory used by Java programs. The GC tracks object no longer being used or referenced by the program and free up memory by removing those objects. The GC works by periodically scanning the heap memory for objects that are no longer referenced by the program. If it finds any such objects, it frees up the memory occupied by those objects. This process is called garbage collection.
Java provides several different algorithms for garbage collection, each with its strengths and weaknesses. The most common algorithm the JVM uses is the mark-and-sweep algorithm, which works by identifying all objects that are no longer reachable by the program and then freeing up the memory occupied by those objects. One of the advantages of using a GC is that it eliminates the need for manual memory management, which can be error-prone and time-consuming. However, the GC does add some overhead to the program, which can affect its performance.
The finalize() method takes no arguments and has a void return type. It is declared protected to ensure that it can only be called by the garbage collector or by a subclass of the class that defines the finalize() method.
Return Value
The finalize() method does not return any value.
How does the Finalize Method in Java Work with Garbage Collection?
The Garbage Collector (GC) automatically manages memory by freeing up memory occupied by unused objects. The GC calls the finalize() method before an object is removed from memory, allowing it to perform any necessary cleanup operations.
However, the finalize() method can have performance implications and should be used cautiously.
Example code for overriding the finalize() method:
public class MyObject {
private File file;
public MyObject(String filename) {
this.file = new File(filename);
}
@Override
protected void finalize() throws Throwable {
try {
if (file != null) {
file.close();
}
} finally {
super.finalize();
}
}
// Other methods here
}
In this example, the MyObject class represents an object that holds a reference to a File object. The finalize() method is overridden to close the file before the GC removes the object from memory.
Why finalize() method in Java is used?
The finalize() method in Java is used for tasks such as closing external resources like files or network connections held by an object before it's garbage collected, releasing native resources to prevent leaks, and implementing custom cleanup logic. However, it's worth noting that as of Java 9, finalize() has been deprecated in favour of more modern resource management techniques like try-with-resources, considered more reliable beyond Java 8.
When to Use finalize() Method in Java?
The garbage collector calls the finalize () method before an object is reclaimed or destroyed. It can be used when you need to tidy up or release resources associated with an object.However, it is essential to note that the finalize() method has been deprecated, and its usage is discouraged. It is generally advised to employ alternative mechanisms for resource cleanup, like implementing the AutoCloseable interface and utilizing the try-with-resources statement. These alternative approaches provide improved control and ensure a predictable and reliable cleanup of resources, making them the preferred and recommended approach.
How to Override finalize() method?
To override the finalize() method in Java, and you can define your own implementation of the method in your class. This allows you to provide custom cleanup behavior for objects of that class.
When you override finalize(), you should include any necessary cleanup code within a try block and call super.finalize() in a finally block to ensure that any necessary cleanup is performed before the object is garbage collected.
Here's an example of how to override the finalize() method in Java:
Java
Java
public class MyClass { private int id;
public MyClass(int id) { this.id = id; }
@Override protected void finalize() throws Throwable { System.out.println("Object with id " + id + " is being destroyed"); super.finalize(); }
public static void main(String[] args) { MyClass obj1 = new MyClass(1); MyClass obj2 = new MyClass(2); MyClass obj3 = new MyClass(3);
Object with id 1 is being destroyed
Object with id 2 is being destroyed
In this example, we create three instances of MyClass and then set obj1 and obj2 to null, so they are eligible for garbage collection. We then call the garbage collector explicitly using System.gc() and Runtime.getRuntime().gc().
When the garbage collector runs, it will call the finalize() method on any objects that are eligible for garbage collection. In this case, it will call finalize() on obj1 and obj2. The program's output will be:
Working of Finalize() Method in Different Scenarios
Here are a few different cases to illustrate how the finalize() method works:
Case 1: Object is garbage collected, but no finalize() method is defined
In this case, the garbage collector will destroy the object without calling any finalize() method.
Java
Java
class MyClass { // No finalize() method defined }
public class Test { public static void main(String[] args) { MyClass obj = new MyClass(); obj = null; System.gc(); // Explicitly call the garbage collector } }
You can also try this code with Online Java Compiler
public class Test { public static void main(String[] args) { MyClass obj = new MyClass(); obj = null; System.gc(); // Explicitly call the garbage collector } }
You can also try this code with Online Java Compiler
In this case, the garbage collector will continue with the destruction of the object, but the exception will be logged to the console.
Java
Java
class MyClass { protected void finalize() throws Throwable { throw new Exception("Exception in finalize() method"); } }
public class Test { public static void main(String[] args) { MyClass obj = new MyClass(); obj = null; System.gc(); // Explicitly call the garbage collector } }
You can also try this code with Online Java Compiler
Exception in thread "Finalizer" java.lang.Exception: Exception in finalize() method
at MyClass.finalize(MyClass.java:3)
at java.base/java.lang.ref.Finalizer.invokeFinalizeMethod(Native Method)
at java.base/java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:170)
As you can see, the exception is logged to the console with details of where it occurred.
Handling Exceptions in Finalize () Method
When the garbage collector calls the finalize() method, it has a specific way of handling exceptions. If an exception occurs while the finalize() method is running, it is usually caught and logged somewhere to keep a record of it. However, the exception itself is not thrown again. This is because the garbage collector calls the finalize() method automatically, and throwing an exception from there can cause some unexpected issues.
The Lifetime of the Finalized Object in Java
In Java, the lifetime of an object with a finalize() method goes through several phases. Here are the phases through which a finalized object passes through its lifetime:
1. Object is created
When an object is created, it is in the "live" phase. The object is allocated memory and can be accessed by the program.
2. Object becomes eligible for garbage collection
When any part of the program no longer references an object, it becomes eligible for garbage collection. At this point, the object enters the "finalizable" phase.
3. Finalize method is called
When the garbage collector determines that an object is eligible for garbage collection, it calls the object's finalize() method before reclaiming its memory. The object is in the "finalized" phase during this process.
4. Object is removed from memory
After the finalize() method completes, the object is removed from memory and enters the "unreachable" phase. The object is no longer accessible, and its memory is eligible for reuse by the JVM.
If the finalize() method resurrects the object by creating a new reference to it, the object will remain in the "finalizable" phase until the finalize() method completes. The object will then re-enter the "live" phase and continue to exist until it becomes eligible for garbage collection again.
Final vs Finally vs finalize() in Java
Below is the table providing the Key differences between the three methods:
Feature
Final
Finally
finalize()
Type
Keyword
Keyword
Method
Purpose
To restrict the modification of a variable, method, or class.
To ensure that a section of code is always executed, even if an exception is thrown.
To perform cleanup processing on an object before it is garbage collected.
Scope
Can be used with classes, methods, and variables.
Can only be used with try/catch blocks.
Can only be used with objects.
Execution
Checked at compile time.
Executed after the try/catch blocks, but before control transfers back to its origin.
Executed just before an object is garbage collected.
Advantages of Finalize Method in Java
The finalize method in Java has some potential advantages, including
It can be used to perform cleanup operations on an object before it is garbage collected, such as releasing resources like file handles or network connections.
It provides a safety net for situations where a programmer may forget to manually clean up an object's resources, ensuring that the resources are eventually released even if the object is no longer referenced.
It can be used in cases where objects need to be "revived" or restored to a previous state after being garbage collected, although this usage is relatively rare.
It can be useful for debugging or profiling, as it allows you to monitor when objects are being garbage collected and potentially identify memory leaks or other issues.
Disadvantages of Finalize Method in Java
The finalize method has some potential drawbacks, including
It is not guaranteed to be called at any particular time or at all, so relying on it for critical cleanup operations can be risky.
It can introduce performance issues, as the JVM must perform additional work to manage finalization and resurrected objects.
It can make it more difficult to reason about the lifecycle of objects in a program, as the behavior of the finalize() method may not be immediately apparent.
It is generally recommended to use other cleanup mechanisms, such as try-with-resources blocks or explicit close() method calls, instead of relying on the finalize() method.
Alternatives to Finalize() Method in Java
Here are some alternatives to using the finalize() method:
Use the try-with-resources statement: This statement was introduced in Java 7 and makes it easy to manage resources that need to be closed when they are no longer needed. Resources that implement the AutoCloseable interface can be used in the try-with-resources statement, automatically calling the close() method on the resource
Use a shutdown hook: A shutdown hook is a thread executed when the JVM is shutting down. This can be used to perform any necessary cleanup before the JVM exits. To use a shutdown hook, you can define a class that extends the Thread class and override the run() method
Use a reference queue: A reference queue is a data structure that holds references to objects that have been garbage collected. By using a reference queue, you can perform cleanup actions on objects that are no longer needed
Use the PhantomReference class: PhantomReference is a special type of reference that gets added to a reference queue when the object it refers to is garbage collected. This can be useful for performing cleanup actions on objects that are no longer needed
Best Practices to Use Finalize() Method in Java Correctly
Best Practices for Correct Usage of the finalize() Method in Java are:
1. Be cautious: It is crucial to keep in mind that the finalize() method is not reliable in terms of when or even if it will be called by the garbage collector. This means relying on finalize() for critical operations or resource cleanup can be risky. Exploring alternative approaches like try-with-resources or implementing the Closeable or AutoCloseable interfaces is strongly recommended
2. Keep it simple: When implementing the finalize() method, it's best to keep it simple and lightweight. Avoid including complex operations, resource-intensive tasks, or any code that could throw exceptions. Remember, the main purpose of finalize() is to handle basic cleanup operations, so it is important to focus on that
3. Avoid object resurrection: It's important to avoid using the finalize() method to bring objects back to life. In other words, we shouldn't try to make objects accessible again by resurrecting them through finalize(). Attempting to do so can cause confusion, make our program behave strangely, and lead to unpredictable results
4. Use super.finalize(): In the finalize() method implementation, It's important to remember to include super.finalize(). This helps ensure the superclass's finalization process is carried out correctly. By doing so, we maintain the expected behaviour of the class hierarchy and allow any essential cleanup tasks defined in the superclass to be performed
5. Consider alternatives: Instead of relying on the finalize() method, it's better to use explicit resource cleanup mechanisms like try-with-resources or implementing the Closeable or AutoCloseable interfaces. These newer approaches offer improved control and predictability when releasing resources
6. Prefer try-finally for cleanup: To ensure that resources are properly cleaned up. It is usually better to use a try-finally block or one of the alternative mechanisms mentioned earlier. These approaches ensure that cleanup operations are performed reliably, regardless of whether the finalize() method is called or not
7. Document intent: If you choose to use the finalize() method in your code, make sure to document its usage and limitations clearly. Explain why it is necessary and any specific precautions or requirements for it to work correctly
Frequently Asked Questions
What is the purpose of the finalize() method in Java?
The purpose of the finalize() method in Java is to perform cleanup tasks or release resources associated with an object before it gets reclaimed by the garbage collector, ensuring that necessary cleanup operations are carried out.
When is the finalize() method called?
The garbage collector calls the finalize () method when an object is ready to be reclaimed or destroyed. It offers a chance to tidy up or release any resources connected to the object. It ensures proper cleanup before removing it from memory.
What is the difference between final & finalize in Java?
In Java, the keyword final indicates that a variable, method, or class cannot be modified or extended. On the other hand, the garbage collector calls the finalize () method before discarding an object. It allows it to perform necessary cleanup or resource release operations.
How many times can finalize method be called in Java?
In Java, the finalize() method is called only once for an object during its lifetime. Once invoked by the garbage collector, it is removed from the finalization queue and will not be called again for that specific object.
What is the difference between finalize and GC in Java?
Finalize() method performs clean up activity and object is finalized. GC destroys the object completely and reclaims the space occupied by the object.
Why is the finalize method protected?
The finalize method is protected to prevent external code from invoking it directly, ensuring it is only called by the garbage collector.
What is the exception in finalize method in Java?
The finalize method can throw any exception; however, uncaught exceptions are ignored, and the object's finalization is terminated.
Conclusion
In this blog, we have discussed the finalize method in java along with the syntax, advantages, and disadvantages. We hope the blog has helped you enhance your knowledge regarding finalize method in Java. If you wish to learn more about Java, you can refer to blogs on