When and How the finalize() Method is Called in Java

Nov 13, 2025 · Programming · 11 views · 7.8

Keywords: Java | finalize method | garbage collection | resource management | method overriding

Abstract: This technical article examines the invocation mechanism of the finalize() method in Java, detailing its execution timing during garbage collection and explaining why it may not execute in test programs. Based on official documentation and best practices, it discusses the uncertain nature of finalize() and presents modern alternatives for resource management. Code examples demonstrate proper method overriding while emphasizing the method's deprecated status and limited applicability in contemporary Java applications.

Fundamental Concepts of finalize()

In the Java programming language, the finalize() method is a protected method defined in the java.lang.Object class. According to official Java documentation, this method is called by the garbage collector when it determines that there are no more references to the object. This means the execution of finalize() is intrinsically linked to the garbage collection process, triggered only when an object becomes eligible for collection and the garbage collector actually runs.

Uncertainty in Invocation Timing

The timing of finalize() method invocation exhibits significant uncertainty. First, an object might remain reachable throughout the entire JVM lifecycle, thus never becoming eligible for garbage collection. Second, even when an object qualifies for collection, the garbage collector may not run immediately, particularly in simple test programs where the JVM might terminate before garbage collection occurs. This uncertainty makes relying on finalize() for critical operations unreliable.

Method Overriding and Practical Examples

Although the finalize() method in the Object class provides an empty implementation, developers can override it to define custom cleanup logic. The following code example demonstrates proper overriding of the finalize() method:

import java.lang.*;

public class ResourceCleanupExample {
    @Override
    protected void finalize() throws Throwable {
        try {
            System.out.println("Performing resource cleanup");
        } catch (Throwable e) {
            throw e;
        } finally {
            super.finalize();
        }
    }
    
    public static void main(String[] args) {
        ResourceCleanupExample obj = new ResourceCleanupExample();
        obj = null; // Make object eligible for garbage collection
        System.gc(); // Suggest JVM to run garbage collection
    }
}

It's important to note that even with explicit calls to System.gc(), there's no guarantee that finalize() will execute, as garbage collector behavior remains non-deterministic.

Modern Alternatives in Java

Given the limitations and deprecated status of finalize(), modern Java development recommends more reliable resource management mechanisms. The try-with-resources statement combined with the AutoCloseable interface provides deterministic resource cleanup guarantees. Additionally, the java.lang.ref.Cleaner class offers more controllable solutions for scenarios requiring post-use cleanup. These alternatives avoid the uncertainties of finalize() while delivering better performance characteristics.

Usage Scenarios and Best Practices

The finalize() method should only be used for cleanup of non-Java resources and should never serve as a critical dependency for application correctness. In practical development, explicit resource management strategies should be prioritized to ensure timely resource release and system stability. For most application scenarios, avoiding the use of finalize() represents the optimal approach.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.