What are the different types of references in Java (strong, soft, weak, phantom)?
Quick Answer
Strong references (ordinary variable assignment) keep an object alive as long as the reference exists — the GC will never collect it. Soft references allow collection only when the JVM is under memory pressure, good for memory-sensitive caches. Weak references allow collection at the next GC cycle regardless of memory pressure, good for metadata that shouldn't keep its key alive (like WeakHashMap). Phantom references are enqueued after an object is already finalized/unreachable, used for precise, GC-driven cleanup scheduling rather than to access the object itself.
Detailed Answer
Beyond ordinary ("strong") references, java.lang.ref provides three reference types with progressively weaker guarantees about keeping an object alive — useful for caching and cleanup scenarios where you want the GC to be able to reclaim memory under pressure.
-
Strong reference: an ordinary reference (
Object o = new Object();). As long as any strong reference chain reaches an object, the GC will never collect it — this is the default and what most code uses. -
SoftReference<T>: the GC is allowed to clear it, but is guaranteed not to until the JVM is actually running low on memory (specifically, before throwingOutOfMemoryError). Ideal for memory-sensitive caches — data you'd like to keep around for reuse, but that's fine to discard and recompute if memory gets tight.
SoftReference<byte[]> cache = new SoftReference<>(loadLargeData());
byte[] data = cache.get(); // null if it was reclaimed under memory pressure
-
WeakReference<T>: the GC clears it at the next collection cycle if no strong references exist, regardless of memory pressure. Used where you need to associate data with an object without preventing that object from being collected — the canonical example isWeakHashMap, whose keys are weakly referenced, so entries automatically disappear once their key is otherwise unreachable (useful for caches/registries keyed by objects with independent lifecycles). -
PhantomReference<T>:get()always returnsnull— it can never be used to access the object. It exists purely to be notified, via aReferenceQueue, after the object has already been finalized and is about to be reclaimed, enabling precise post-mortem cleanup scheduling (e.g., releasing native/off-heap memory tied to the object) more reliably than the deprecatedfinalize().
Strength ordering (strongest to weakest): Strong > Soft > Weak > Phantom — each is collected more eagerly than the last.