When does Java's finalize() method get called?

What is the exact moment when the finalize() method is called in Java?

I am trying to understand when the Java finalize method gets executed by the JVM. To test this, I created a class where I override finalize() to write into a file when it is called. However, it seems that finalize() is not executing as expected.

Can anyone explain why this is happening and under what conditions the finalize() method actually runs in Java?

Hey! I’ve worked with Java for a while, and I can tell you that the java finalize method is not called immediately when an object becomes unreachable. Instead, the JVM invokes finalize() only when the garbage collector decides to clean up the object. Even then, there’s no guarantee it will execute before the program exits.

If you’re testing this by creating an object and expecting finalize() to run instantly, it won’t happen. The garbage collector runs at its own discretion. You can call System.gc() to request garbage collection, but it’s just a suggestion—the JVM may or may not act on it immediately.

Yeah, I agree with @charity-majorsjava finalize is unpredictable. But if you really want to see it in action, you can try forcing garbage collection. Here’s how:

public class TestFinalize {  
    @Override  
    protected void finalize() throws Throwable {  
        System.out.println("finalize() method called!");  
    }  

    public static void main(String[] args) {  
        TestFinalize obj = new TestFinalize();  
        obj = null; // Make object eligible for GC  

        System.gc(); // Request garbage collection  
        System.runFinalization(); // Suggest finalization  
    }  
}

By using System.gc() along with System.runFinalization(), you increase the chance of finalize() being called. But still, it’s not guaranteed. That’s why relying on finalize() for critical tasks (like closing files or releasing resources) is risky—it might not run in time or at all.

Absolutely, @dipen-soni makes a good point. Since java finalize is unreliable, the best practice is to avoid using it for resource management altogether. Instead, you should use AutoCloseable and try-with-resources for proper cleanup. This ensures that resources are released immediately when they go out of scope, without depending on the garbage collector.

Here’s how:

class MyResource implements AutoCloseable {  
    public void writeToFile() {  
        System.out.println("Writing to file...");  
    }  

    @Override  
    public void close() {  
        System.out.println("Cleaning up resources...");  
    }  
}  

public class Main {  
    public static void main(String[] args) {  
        try (MyResource resource = new MyResource()) {  
            resource.writeToFile();  
        } // `close()` is automatically called here  
    }  
}

By using try-with-resources, you guarantee that the close() method executes immediately after the block, ensuring proper resource cleanup—no waiting for garbage collection!