What is a SoftReference in Java, and when does the garbage collector clear one?
answer
- Cleared only under memory pressure, before OutOfMemoryError
- Soft = lazy clear; weak = eager clear at next GC
- get() returns referent or null — always null-check
- Referent = the wrapped object; softly reachable
- Good for memory-sensitive caches, not robust caches
basics
~10 sA SoftReference is a special wrapper around an object that lets the garbage collector throw that object away, but only when the JVM is running low on memory. Until then, the object stays alive.
solid answer
~40 sA SoftReference (java.lang.ref.SoftReference) holds a reference to an object — the referent — in a way that does not, by itself, keep that object alive forever. The garbage collector may reclaim a softly-reachable object, but the contract says it should do so only in response to memory pressure: typically just before the JVM would otherwise throw an OutOfMemoryError. You read the referent with get(), which returns the object or null if it has been cleared. Because the object can survive many GC cycles while memory is plentiful, SoftReferences are the standard building block for memory-sensitive caches — data you'd like to keep but can afford to lose when the heap gets tight. You must always null-check the result of get() and be able to recompute or reload the value when it returns null.
go deeper
Knows a SoftReference wraps an object, get() may return null, and the GC clears it only when memory runs low — unlike a normal (strong) variable that is never collected.
Can contrast soft vs weak clearing semantics, explain softly-reachable, and write a correct null-checking get-or-recompute cache read.
Explains the 'cleared before OutOfMemoryError' contract, the non-deterministic LRU-style heuristic (SoftRefLRUPolicyMSPerMB), and why SoftReference alone is a weak caching strategy versus a real cache library.
Reasons about heap-sizing and GC interactions: soft refs survive across collections, can mask leaks, cause a cliff where all entries clear at once, and add GC pressure; recommends bounded caches with explicit eviction over soft-ref maps for production caching.
## The problem soft references solve In Java you normally hold an object through an **ordinary variable** — a *strong reference*. As long as any strong reference to an object is reachable from a **GC root** (a starting point the collector treats as always-live: local variables on a thread's stack, static fields, etc.), the **garbage collector (GC)** — the JVM subsystem that automatically frees the memory of unreachable objects — will *never* reclaim that object. That is what you want for live program data, but it is awkward for a *cache*: a cache holds copies of expensive-to-produce data so you can reuse them, yet you'd happily discard those copies rather than run out of memory. A strong reference can't express "keep this *unless* you need the space." ## What a SoftReference is `java.lang.ref.SoftReference<T>` is a wrapper object. You create it with `new SoftReference<>(obj)`; `obj` is called the **referent**. The SoftReference holds the referent *softly* instead of strongly. You retrieve the referent by calling `get()`, which returns either the referent or `null` if the GC has already reclaimed it. An object is **softly reachable** when (a) it is *not* strongly reachable — no chain of ordinary references from a GC root reaches it — but (b) it *can* be reached by following at least one SoftReference. The whole point: once the only thing keeping an object alive is a SoftReference, the GC is *permitted* to clear it. ## When does the GC clear it? The contract (from the `java.lang.ref` documentation) says: the GC **may** clear softly-reachable references at its discretion, but is *encouraged* to retain them as long as memory is comfortable and to clear them **before throwing an OutOfMemoryError**. In practice the HotSpot JVM uses a heuristic: it keeps a soft referent for roughly `SoftRefLRUPolicyMSPerMB` milliseconds of lifetime *per megabyte of free heap* since it was last accessed (default 1000 ms/MB). So with more free memory, soft referents live longer. When the heap fills, the GC clears them — oldest/least-recently-used first — to avoid an OOM. Two consequences: clearing is **not deterministic** (you cannot predict exactly when), and a single full GC under pressure can clear *all* of them at once. ## Soft vs weak — the key contrast A `WeakReference` is cleared **eagerly**: as soon as its referent is only weakly reachable, the *next* GC reclaims it, regardless of how much memory is free. A SoftReference is cleared **lazily**, only under memory pressure. Mnemonic: *weak = clear ASAP; soft = clear only if needed.* This makes SoftReference the natural fit for caches (keep as long as you can) and WeakReference the fit for canonicalizing/metadata maps where you want entries to vanish promptly. ## How you actually use one Because `get()` can return `null` at any time, every read must null-check and have a fallback that recomputes or reloads the value. SoftReference does *not* make a robust cache by itself — it has no size bound, no eviction policy beyond the GC's, and clears everything under pressure. Modern code usually prefers a real cache library (Caffeine, Guava) with explicit size/time eviction; soft references are a low-level primitive and a frequent interview topic.
- What is the practical difference between a SoftReference and a WeakReference?Both allow the GC to reclaim the referent once no strong reference remains, but a WeakReference is cleared eagerly at the very next GC, whereas a SoftReference is retained until the JVM is under memory pressure (and cleared before an OutOfMemoryError). So soft is for memory-sensitive caches; weak is for prompt cleanup like WeakHashMap keys.
- Why must you always null-check the result of SoftReference.get()?Because the GC can clear the referent between the time you created the reference and the time you read it, get() may return null at any point. Your code needs a fallback that recomputes or reloads the value rather than assuming it is still cached.
saying these in an interview costs you the question
- Saying a SoftReference is cleared at the next GC like a WeakReference — it survives until memory pressure
- Claiming the GC guarantees to keep softly-reachable objects (it only 'should' retain them; it may clear at discretion)
- Forgetting to null-check get() and assuming the cached value is always present
- Treating SoftReference as a complete cache with eviction and bounds