skip to content

Soft References

SoftReferences are cleared only when the JVM is short on memory, just before it would throw OutOfMemoryError, which makes them a natural fit for memory-sensitive caches. Interviewers ask soft versus weak: soft holds on under pressure, weak lets go at the next collection.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

4

What is a SoftReference in Java, and when does the garbage collector clear one?

level: juniorimportance: must knowfreq 55%

answer

  1. Cleared only under memory pressure, before OutOfMemoryError
  2. Soft = lazy clear; weak = eager clear at next GC
  3. get() returns referent or null — always null-check
  4. Referent = the wrapped object; softly reachable
  5. Good for memory-sensitive caches, not robust caches

basics

~10 s

A 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 s

A 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

for a junior

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.

for a middle

Can contrast soft vs weak clearing semantics, explain softly-reachable, and write a correct null-checking get-or-recompute cache read.

for a senior

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.

for a principal

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

context

open as a page

Contrast SoftReference and WeakReference: how do their clearing policies differ, and which fits a memory-sensitive cache versus a WeakHashMap-style side table?

level: middleimportance: must knowfreq 60%

basics

~20 s

A weak reference is thrown away as soon as the next garbage collection runs once nothing else points to the object. A soft reference is kept longer — the collector only clears it when memory is running low. So soft is for caches you want to keep; weak is for cleanup that should happen quickly.

open as a page

What are the pitfalls of building a cache out of SoftReferences, and why are bounded caches like Caffeine usually preferred?

level: seniorimportance: should knowfreq 42%

basics

~20 s

A soft-reference cache has no size limit and no real eviction rules of its own — it just hopes the garbage collector will clear things at the right time. Under memory pressure it can dump everything at once and slow the app down. A real cache library lets you set size and time limits, so it behaves predictably.

open as a page

How does HotSpot decide when to clear soft references, and how does that interact with heap sizing, GC choice, and the SoftRefLRUPolicyMSPerMB flag?

level: principalimportance: nice to knowfreq 22%

basics

~20 s

HotSpot keeps a soft-referenced object based on how much free memory there is and how long ago it was last used: more free memory means it lives longer. A JVM flag controls that ratio. Because it depends on free heap, the same code keeps soft references for different amounts of time depending on heap size and the garbage collector you run.

open as a page