Java Finalize Method (Deprecated)
Object has a method called finalize() that the garbage collector was supposed to call just before destroying an object, so the object could release files, sockets or other resources. It sounded useful, and old code and interview questions still mention it. In practice it was unreliable, slow and dangerous, so it was deprecated in Java 9 and is now marked for removal. This lesson explains why, and shows what to use instead.
The Warning You'll See
public class Fin {
@Override
protected void finalize() { System.out.println("cleanup"); }
}Fin.java:3: warning: [removal] finalize() in Object has been deprecated and marked for removal
protected void finalize() { System.out.println("cleanup"); }
^
1 warningIt still compiles, but the compiler is telling you that a future Java version will remove it. Since Java 18 you can even switch finalization off completely with java --finalization=disabled, to test whether your program secretly depends on it.
Why It Never Worked Well
| Problem | Why it matters |
|---|---|
| No guarantee it runs | The GC may never collect the object before the program ends |
| No guarantee when | It might run seconds or minutes later, so files and connections stay open |
| Slow | Objects with finalizers need extra GC work and survive longer |
| Can resurrect objects | finalize can store this somewhere, bringing a "dead" object back |
| Exceptions are ignored | An exception thrown in finalize is silently swallowed |
| Security holes | Finalizer attacks could use half-built objects |
What to Use Instead
The right tool is to close resources yourself, at a known moment. Any class can opt in by implementing AutoCloseable, and a try-with-resources statement closes it automatically, even if an exception is thrown:
public class Receipts {
static class ReceiptPrinter implements AutoCloseable {
private final String counter;
ReceiptPrinter(String counter) {
this.counter = counter;
System.out.println("Printer opened at " + counter);
}
void print(String customer, long amount) {
System.out.println("Receipt: " + customer + ", Rs. " + amount);
}
@Override
public void close() {
System.out.println("Printer closed at " + counter);
}
}
public static void main(String[] args) {
try (ReceiptPrinter p = new ReceiptPrinter("Counter 3")) {
p.print("Advitha", 640);
p.print("Navika", 1210);
}
System.out.println("Done");
}
}Printer opened at Counter 3
Receipt: Advitha, Rs. 640
Receipt: Navika, Rs. 1210
Printer closed at Counter 3
DoneHow it works
ReceiptPrinterimplementsAutoCloseable, which has one method:close().try (ReceiptPrinter p = ...)declares the resource in parentheses. When the block ends, normally or through an exception, Java callsp.close()automatically.- The cleanup happens at a known point, before
"Done", whichfinalizecould never promise.
Files, streams, database connections and sockets in the JDK all implement AutoCloseable, and the later lessons on exceptions and file I/O use them heavily.
Common Mistakes
Relying on finalize or the GC to close files. Close them explicitly with try-with-resources.
Calling System.gc() to "make finalize run". It's only a hint, and the timing is still unpredictable.
Answering "finalize is like a C++ destructor". Destructors run at a known time; finalize may never run.
Interview Corner
What is finalize() and why is it deprecated?
finalize() is a protected method of Object that the garbage collector could call before reclaiming an object, intended for releasing resources. It's deprecated, and marked for removal, because there's no guarantee it runs or when, it slows garbage collection, exceptions in it are ignored, it can resurrect objects, and it enabled security attacks. Resources should be released explicitly with try-with-resources, with Cleaner as an optional safety net.
What is the difference between final, finally and finalize?
final is a keyword that makes a variable unchangeable, a method non-overridable or a class non-extendable. finally is a block after try that always runs, used for cleanup. finalize() is a deprecated Object method that the garbage collector might call before reclaiming an object.
Practice
- Easy: Write a
Sessionclass that implementsAutoCloseable, prints when it opens and closes, and use it with try-with-resources. - Harder: Throw an exception inside the try block of
Receiptsafter the first receipt, and catch it outside. Doesclose()still run? In which order are the lines printed?
Key Takeaways
Was this tutorial helpful?