How does a strong reference differ from soft, weak, and phantom references in terms of when the garbage collector may reclaim the referent?
answer
- Ladder: Strong > Soft > Weak > Phantom
- Soft = memory pressure; Weak = next GC; Phantom = post-mortem notify
- Strongest reachability wins — strong suppresses the weaker ones
- WeakHashMap on weak keys; caches on soft; Cleaner on phantom
- PhantomReference.get() always returns null
basics
~20 sA strong reference keeps an object alive as long as it is reachable. Soft references are cleared only under memory pressure, weak references at the next GC once no strong refs remain, and phantom references are used only for post-cleanup notification.
solid answer
~50 sAll four reference strengths describe how easily the garbage collector may reclaim the object they point to (the referent). A strong reference is the strongest: while the object is strongly reachable from a GC root it is never collected. A SoftReference is reclaimed only when the JVM is running low on memory, just before it would throw OutOfMemoryError, which makes it suitable for memory-sensitive caches. A WeakReference is reclaimed eagerly at the next GC cycle as soon as no strong reference remains, regardless of memory pressure; WeakHashMap is built on this. A PhantomReference is the weakest: get() always returns null, and it exists purely so you can be notified (via a ReferenceQueue) after the referent has been collected, for finalizer-free cleanup. The crucial rule is that strong reachability always overrides the weaker types: if any strong reference to the object exists, the soft/weak/phantom behavior is suppressed and the object stays alive.
code
java · 8 linesObject obj = new Object();
WeakReference<Object> weak = new WeakReference<>(obj);
System.out.println(weak.get() != null); // true: 'obj' keeps it strongly reachable
obj = null; // drop the only strong reference
System.gc(); // hint to run the collector
// After collection, weak.get() returns null because only a weak ref remained
System.out.println(weak.get() == null); // typically truego deeper
Knows the four names exist and that strong is the default that keeps an object alive; may be fuzzy on the exact soft-vs-weak timing.
States the clearing condition for each (strong=never while reachable, soft=memory pressure, weak=next GC, phantom=post-mortem) and names WeakHashMap and memory-sensitive caches as uses.
Articulates that the strongest reachable reference determines fate, maps each type to a concrete design (cache, auto-evicting map, Cleaner), and relates phantom references to the finalizer replacement.
Reasons about reachability strength as a platform contract, weighs soft-reference cache pitfalls (GC pauses, unpredictability) versus explicit eviction, and designs cleanup strategies around ReferenceQueue/Cleaner instead of finalization.
## The four reference strengths Java defines an ordered ladder of **reference strengths**. Each describes how willing the **garbage collector (GC)** — the runtime process that reclaims unused memory — is to delete the object a reference points to. The pointed-to object is called the **referent**. From strongest (most resistant to collection) to weakest: 1. **Strong reference** — the ordinary kind: `Object o = new Object();`. While the referent is reachable from a **GC root** (a trusted always-live anchor such as a thread's stack variable or a static field) through strong references, it is **never** collected. 2. **Soft reference** (`java.lang.ref.SoftReference`) — the referent is kept *as long as possible* and is cleared **only when the JVM is under memory pressure**, i.e. roughly just before it would otherwise throw `OutOfMemoryError`. Good for **memory-sensitive caches**: keep cached data while there is room, sacrifice it when memory is tight. 3. **Weak reference** (`java.lang.ref.WeakReference`) — the referent is cleared **eagerly at the next GC** once no strong (or soft) reference remains, *regardless* of memory pressure. The canonical use is **`WeakHashMap`**, whose keys are weakly held so entries disappear automatically once a key is otherwise unreachable. Good for canonicalizing maps and metadata side-tables. 4. **Phantom reference** (`java.lang.ref.PhantomReference`) — the weakest. Its `get()` **always returns `null`**, so you can never resurrect or use the referent through it. Its only purpose is **post-mortem notification**: paired with a `ReferenceQueue`, the GC enqueues the phantom reference *after* the referent has been collected, letting you run cleanup (e.g. release native/off-heap resources). The modern `Cleaner` API is built on this and replaces the deprecated `finalize()`. ## The decisive rule: strong reachability wins The single most important point in an interview: **if an object is reachable through even one strong reference, the weaker references to it do nothing.** Strength is determined by the *strongest* reference that can reach the object. For example: ```java Object obj = new Object(); // strong reference WeakReference<Object> weak = new WeakReference<>(obj); // 'obj' is strongly reachable, so the GC will NOT clear 'weak' yet. obj = null; // drop the strong reference // Now only a weak reference reaches it -> eligible for clearing at the next GC. ``` So `weak.get()` returns the object while `obj` is still set, and starts returning `null` after the strong reference is dropped and a GC runs. ## How to reason about each in practice - **Strong** — default; use for anything that must stay alive while in use. The source of most **memory leaks** when held unintentionally (e.g. an object stuck in a long-lived static collection or a never-deregistered listener stays strongly reachable and so never collected). - **Soft** — caches that should shrink under pressure rather than cause `OutOfMemoryError`. - **Weak** — auto-evicting maps / associations that must not keep their keys alive. - **Phantom** — deterministic-ish cleanup hooks that fire after collection (via `Cleaner`). ## Why the ladder exists Without the weaker types you would have only two options: hold an object strongly (it never dies) or not at all (you cannot reach it). The `java.lang.ref` ladder gives intermediate contracts — 'keep it unless memory is tight', 'keep it only until the next GC', 'tell me after it dies' — all defined **relative to the strong-reference baseline**. That baseline is therefore the concept you must understand first.
- If you hold both a strong and a weak reference to the same object, when is it collected?Not until the strong reference is gone. Strength is set by the strongest reachable reference, so the weak reference is irrelevant while the strong one keeps the object reachable from a root.
- Why can't you use a PhantomReference to access its referent?PhantomReference.get() is defined to always return null. Its purpose is post-collection notification via a ReferenceQueue, not access, which prevents resurrecting an object that is already being cleaned up.
Think of guests in a hotel. A strong reference is a permanent resident — never evicted. A soft reference is a guest the hotel keeps until rooms run short. A weak reference is a guest checked out the very next housekeeping round once no one vouches for them. A phantom reference is a note left so the front desk is told only after the room has been cleared.
saying these in an interview costs you the question
- Saying a weak reference is cleared only under memory pressure (that's soft; weak clears at the next GC regardless).
- Saying a soft reference is cleared at every GC (it survives until memory pressure).
- Thinking a weak/soft reference can override a coexisting strong reference and let the object die.
- Claiming PhantomReference.get() returns the object.