skip to content

Walk through the full lifecycle of a Java object from creation to memory reclamation.

level: seniorimportance: should knowfreq 58%

answer

  1. create: alloc → default-init → super/init/ctor → reference
  2. reachable while a root-path exists (aliasing)
  3. eligible when last reference dropped
  4. collection timing is JVM's, not yours
  5. finalize deprecated; Cleaner GC-timed; use try-with-resources
  6. reference strengths: strong/soft/weak/phantom

basics

~20 s

An object is created with new (memory allocated, fields defaulted, constructor run), used while reachable through references, becomes eligible for GC when no longer reachable, then is collected and its memory reclaimed at some later time.

solid answer

~40 s

The lifecycle has clear stages. **Creation:** `new` allocates heap memory, zero-initializes fields, runs field initializers and the constructor chain (super first), and returns a reference. **In use (reachable):** the object lives as long as a chain of references reaches it from a GC root; aliasing means multiple references may keep it alive. **Unreachable / eligible:** when the last reference is dropped (scope exit, reassignment, null), the object becomes eligible for GC. **Collection:** at an unspecified later time the collector reclaims the memory; if the object had a `finalize`/`Cleaner` action it may run first (but timing is not guaranteed, so don't depend on it). Two important nuances: eligibility is not immediate freeing, and external resources (files, sockets) should be released deterministically with try-with-resources rather than relying on GC.

code

java · 10 lines
java
class Account {
    int balance;                 // default 0 before ctor body
    { balance = 10; }            // instance initializer runs after super(), before ctor body
    Account(int b) { super();    // implicit; parent built first
                     balance = b; }
}

Account a = new Account(100);    // created + reachable
a = null;                        // eligible for GC (no other reference)
// memory reclaimed later, at the collector's discretion

go deeper

for a junior

Lists the basic stages: created with new, used, then garbage-collected when unused.

for a middle

Explains creation steps and that eligibility depends on reachability, distinct from when collection happens.

for a senior

Covers constructor ordering (super → initializers → body), the eligibility/collection gap, finalize deprecation, and try-with-resources for deterministic cleanup.

for a principal

Adds reference strengths (soft/weak/phantom), Cleaner vs finalize trade-offs, allocation internals (TLAB), and how object-lifetime patterns interact with generational/region GCs.

## The stages, end to end Think of an object as moving through phases. Each phase has a precise meaning. ### 1. Creation (instantiation) Triggered by `new T(...)` (or equivalents like deserialization, reflection, cloning): 1. **Allocation** — the JVM reserves heap memory sized for a `T` (often from a fast thread-local buffer, a *TLAB*). 2. **Default initialization** — all instance fields are set to zero-values (`0`/`false`/`null`). No field is ever garbage. 3. **Constructor chain** — the constructor runs. Its first action is an implicit or explicit call to a **super-constructor** (`super(...)`), so the parent is fully initialized before the child. Then **instance field initializers** and **instance initializer blocks** run in source order, followed by the constructor body. 4. **Reference returned** — `new` evaluates to a reference, normally stored in a variable or field, making the object **reachable**. ### 2. In use — the reachable phase The object is alive as long as some chain of references reaches it from a **GC root** (a live stack local, a static field, an active thread, a JNI handle). During this phase: - Multiple references may point at it (**aliasing**); any of them keeps it alive. - Its state can be read and mutated through any reference. ### 3. Becoming unreachable — eligibility When the **last** reference path disappears — a local goes **out of scope**, a variable is **reassigned**, or set to **null** — and no other reachable reference remains, the object becomes **eligible for garbage collection**. Reachability is transitive and handles cycles correctly (an isolated island of mutually-referencing objects with no root path is eligible). ### 4. Collection — reclamation At an unspecified later time, when the collector runs (driven by allocation pressure), it traces from the roots, finds the eligible object, and reclaims its memory for reuse. Eligibility and reclamation are **decoupled** — there is no defined moment of freeing, and `System.gc()` is only a hint. ### 5. Finalization (legacy / discouraged) Historically, if a class overrode **`finalize()`**, the GC would queue and run it once before reclaiming the object — but timing was unpredictable, it could *resurrect* the object, and it slowed collection. `finalize()` is **deprecated**. The modern replacement is **`java.lang.ref.Cleaner`** (or `PhantomReference`), still GC-timed, so also not for deterministic cleanup. **For external resources, use `AutoCloseable` + try-with-resources** for deterministic release. ## Reference strengths affect the phase boundaries Beyond ordinary (strong) references, Java has: - **SoftReference** — cleared only under memory pressure (good for caches). - **WeakReference** — cleared as soon as the object is otherwise weakly reachable (good for canonicalizing maps; `WeakHashMap`). - **PhantomReference** — for post-mortem cleanup actions, enqueued after the object is finalizable. These let you keep a handle to an object *without* keeping it strongly alive. ## Putting it together ```text new → [allocated + initialized] → reachable (in use) → last reference dropped → eligible for GC → (collector runs) → memory reclaimed ``` The two facts interviewers probe: **creation order** (super → field inits → constructor body) and **the eligibility-vs-collection gap** (you control reachability; the JVM controls timing).

  • In what order do super-constructor, instance field initializers, and the constructor body run?
    super-constructor first (parent fully initialized), then instance field initializers and instance initializer blocks in source order, then the constructor body.
  • Why shouldn't you rely on finalize()/Cleaner to close a file?
    Their execution is tied to GC timing, which is unspecified and may never happen promptly, so the file could stay open indefinitely. Use try-with-resources/AutoCloseable for deterministic release.

An object's life is like a library book: acquired and catalogued (creation), checked out and read by patrons (reachable/aliased), returned with no holds on it (eligible), and eventually pulped during a clear-out (collection) — but the exact day of pulping is the librarian's call, not yours.

saying these in an interview costs you the question

  • Saying the constructor body runs before the super-constructor
  • Treating eligibility and reclamation as the same instant
  • Recommending finalize() for resource cleanup
  • Ignoring that reachability (not scope alone) governs lifetime
  • Not knowing weak/soft references exist

context