advanced.java
← All concepts
Object lifecycle · ch. 1, p. 4

Garbage collection and finalizers

The collector reclaims objects unreachable from any GC root, on no schedule you can rely on. finalize() is deprecated and unusable for resource release; Cleaner or try-with-resources is the answer.

Reachability, not scope, decides collection. An object is collectable once no chain of references reaches it from a GC root — a live thread’s stack, a static field, or a JNI reference.

Why finalize() fails

  • It may never run. The JVM is allowed to exit without finalising anything.
  • It runs on an unspecified thread at an unspecified time.
  • It costs at least two GC cycles, because a finalizable object must survive one collection to be finalised and another to be freed.
  • Resurrecting this inside it is legal, which makes the whole design unsound.
// The replacement
class Handle implements AutoCloseable {
    @Override public void close() { /* release here */ }
}

try (Handle h = new Handle()) {
    // deterministic release at the end of the block
}

Reference types, weakest last

SoftReference is cleared under memory pressure, WeakReference at the next collection, PhantomReference only after the object is finalised — the last being the basis for Cleaner, the sanctioned post-mortem hook.

2 questions on this concept Drill it