How does HotSpot decide when to clear soft references, and how does that interact with heap sizing, GC choice, and the SoftRefLRUPolicyMSPerMB flag?
answer
- Keep-if idle-time < SoftRefLRUPolicyMSPerMB (1000 default) × free-MB
- More free heap → soft refs live longer; capacity emerges from -Xmx
- =0 clears on every GC, making soft ≈ weak
- Reference processing happens in-GC → adds pause time; bulk-clear on full GC
- Coupling cache size + eviction to heap/GC is the anti-pattern — prefer bounded caches
basics
~20 sHotSpot 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.
solid answer
~60 sHotSpot's soft-reference policy is timestamp-and-free-memory based. Each soft referent records when it was last accessed; on a GC the collector keeps it if its idle time is below a threshold computed as SoftRefLRUPolicyMSPerMB (default 1000 ms) multiplied by the amount of free heap in megabytes. So with lots of free memory, soft referents survive for a long idle window; as free memory shrinks, the window shrinks, and a referent clears once its idle time exceeds it — effectively a global LRU under memory pressure. Crucially the policy is keyed to *free heap after collection*, which is why a larger -Xmx makes soft references far stickier, while a tight heap clears them aggressively. The GC algorithm matters too: reference processing happens during the collection, so soft-ref-heavy heaps add to pause time, and low-pause collectors (G1, ZGC) handle the same flag but with their own reference-processing characteristics. As an architect you tune SoftRefLRUPolicyMSPerMB (or set it to 0 for immediate clearing on every GC) only with care — most teams instead avoid coupling cache lifetime to this heuristic and use a bounded cache.
go deeper
Knows soft references are cleared by the GC under low memory and that a JVM flag affects how long they survive.
Understands that more free heap keeps soft references alive longer and can name SoftRefLRUPolicyMSPerMB as the controlling flag.
Explains the idle-time < ms-per-MB × free-MB formula, the LRU-under-pressure behavior, =0 as weak-like clearing, and the reference-processing GC cost.
Reasons about the coupling of cache capacity/eviction to heap sizing and GC choice, the bulk-clear-on-full-GC cliff, per-collector differences, and argues for bounded instrumented caches with soft refs only as an OOM backstop and the flag as a diagnostic.
## The decision the GC must make When a collection runs, the GC encounters objects that are **softly reachable** — reachable only through `SoftReference`s. For each it must decide: keep the referent, or clear the reference (set its referent to `null`, optionally enqueue it). The contract says retain while memory is comfortable, clear before `OutOfMemoryError`. HotSpot turns that into a concrete, tunable formula. ## HotSpot's formula HotSpot records, for each `SoftReference`, a **clock/timestamp** of when its referent was last accessed (via `get()`), updated by the collector's reference-processing phase. On a GC it computes an **interval** = `SoftRefLRUPolicyMSPerMB` (default **1000** ms) × **free heap in megabytes** (measured for the relevant generation/space after the collection's live-set is known). A soft referent is **kept** if its idle time (now − last-access timestamp) is **less than** that interval, and **cleared** otherwise. Two properties fall out: 1. **More free heap → longer retention.** With 4 GB free and the default 1000 ms/MB, the interval is enormous, so essentially all soft referents survive. As free heap falls toward zero, the interval collapses and referents clear — oldest (least recently accessed) first, giving a **global LRU** ordering under pressure. 2. **Last-access matters.** Touching a soft referent via `get()` refreshes its timestamp, so frequently used entries are retained longer than idle ones — a crude recency policy. ## Heap sizing is the dominant lever Because the interval scales with **free** heap, the *single biggest factor* in how long soft references live is how much headroom your heap has. The same application with `-Xmx2g` versus `-Xmx16g` will clear soft references at wildly different rates: on the big heap they may *never* clear in normal operation; on the small heap they clear constantly. This is why a soft-ref cache's effective capacity is an *emergent property of heap sizing*, not a property you set — a frequent source of 'works on my machine, thrashes in prod' surprises. ## The tuning flag and the two extremes - `-XX:SoftRefLRUPolicyMSPerMB=<n>`: raises/lowers the ms-per-MB multiplier. Larger → stickier soft refs (more memory used for caching, less for everything else); smaller → more aggressive clearing. - `-XX:SoftRefLRUPolicyMSPerMB=0`: clears soft referents on **every** GC — making `SoftReference` behave essentially like `WeakReference`. Useful to *prove* a suspected soft-ref retention problem or to minimize footprint at the cost of cache value. Note: with **AOT/older specifics** aside, this flag is the standard HotSpot knob; other JVMs may differ. ## GC algorithm interactions **Reference processing** — walking the discovered soft/weak/phantom references to decide and clear them — happens *within* the GC. A heap with millions of soft references lengthens this phase and thus **pause time**; some collectors parallelize it (`-XX:+ParallelRefProcEnabled`). Generational collectors only reconsider soft references in the spaces they collect, so a referent may persist through many young collections and only be re-evaluated on an old/full GC — meaning a soft-ref cache often clears in bulk on the *full* GC, reinforcing the **clearing cliff**. Low-pause collectors (G1, ZGC, Shenandoah) honor the same flag but with different reference-processing concurrency and timing, so the *observed* retention can vary by collector even at identical flags. ## The architect's stance The deep lesson is **coupling**: relying on soft references couples your *cache capacity* and *eviction timing* to *heap size and GC behavior* — three things you usually want to tune **independently**. Capacity is a product/SLA decision; GC is a latency decision; tying them together makes both harder to reason about and turns capacity into something that silently changes when ops adjust `-Xmx` or swaps collectors. The mature pattern is a **bounded, instrumented cache** (explicit `maximumSize`/`expireAfter`, hit-rate metrics) that decides eviction itself, optionally with soft/weak values only as an **OOM backstop**. Reach for `SoftRefLRUPolicyMSPerMB` mainly as a *diagnostic* (set 0 to test) or a narrow tuning measure, not as a primary cache-sizing mechanism.
- What does setting -XX:SoftRefLRUPolicyMSPerMB=0 do, and when would you use it?It makes the retention interval zero, so soft referents are cleared on every GC — effectively turning SoftReference into WeakReference. It's useful as a diagnostic to confirm that soft-reference retention is responsible for high heap usage, or to minimize footprint when caching value isn't worth the memory; you wouldn't normally run production this way if you actually want a cache.
- Why can a soft-reference cache behave very differently between a 2 GB and a 16 GB heap?Because HotSpot's retention interval scales with free heap (ms-per-MB × free MB). On a 16 GB heap there is usually so much headroom that soft referents almost never clear, so the 'cache' grows large; on a 2 GB heap the interval is small and referents clear frequently. Effective cache capacity is thus an emergent property of heap sizing, not something the code sets.
saying these in an interview costs you the question
- Saying the clearing time is fixed/deterministic regardless of heap size
- Believing SoftRefLRUPolicyMSPerMB sets a wall-clock TTL independent of free memory
- Assuming soft references are re-evaluated on every young GC (often only on full/old GC)
- Treating soft-ref cache capacity as a tunable you set directly rather than an emergent effect of -Xmx