What is reachability in the context of GC?
4. Phantom — object almost removed 5. Unreachable — garbage
Junior Level
Reachability — object status: can it be reached from code.
5 levels:
- Strong — normal reference (
Object obj = new Object()) - Soft — removed when memory is low
- Weak — removed at next collection
- Phantom — object almost removed
- Unreachable — garbage
Middle Level
Reference Types
| Type | When removed | Use case |
|---|---|---|
| Strong | Never | Business objects |
| Soft | On OOM threat | Caches |
| Weak | At next GC | WeakHashMap |
| Phantom | After finalization | Resource cleanup |
// Soft Reference
SoftReference<Data> ref = new SoftReference<>(data);
Data cached = ref.get(); // null if GC removed
// Weak Reference
WeakReference<User> ref = new WeakReference<>(user);
// GC removes at nearest collection
// Phantom Reference
PhantomReference<Resource> ref = new PhantomReference<>(resource, queue);
// get() always null! Only for tracking removal
Cleaner (Java 9+)
// Replacement for finalize()
Cleaner cleaner = Cleaner.create();
Cleanable cleanable = cleaner.register(obj, () -> {
nativeFree(handle); // Cleanup
// handle is a native pointer (long), obtained from JNI/MemorySegment.
// Cleaner allows freeing native memory that GC doesn't control.
});
cleanable.clean(); // Manual cleanup
Senior Level
SoftReference Formula
JVM cleans when:
current_time - last_access < free_memory × SoftRefLRUPolicyMSPerMB
Default: 1000 ms per each MB
→ "9 hours" — theoretical maximum at 32 GB free and default policy.
→ In practice, SoftReferences are cleaned much earlier under load.
Tuning: -XX:SoftRefLRUPolicyMSPerMB=100
Reference Handler Thread
High-priority system thread:
1. GC detects reachability change
2. Object → Pending List
3. Reference Handler → ReferenceQueue
4. Application polls queue
→ Asynchronous, doesn't block GC
Resurrection
// ❌ In finalize() you can resurrect an object
protected void finalize() {
GlobalCache.add(this); // Strong reference → object alive!
}
// Cleaner cannot resurrect:
// → Lambda does NOT have reference to this
Best Practices
- Strong = business logic
- Soft = caches (tune SoftRefLRUPolicyMSPerMB)
- Weak = metadata
- Phantom/Cleaner = native resources
- Avoid resurrection
- ReferenceQueue for monitoring
Senior Summary
- 5 levels of reachability
- Soft = caches, cleanup on OOM threat
- Weak = next collection
- Phantom = removal tracking
- Cleaner = finalize() replacement
- Reference Handler = async thread
- Resurrection = architectural evil
Interview Cheat Sheet
Must know:
- 5 reachability levels: Strong (normal reference), Soft (on low memory), Weak (at next GC), Phantom (after finalization), Unreachable (garbage)
- SoftReference: for caches; cleanup formula:
free_memory × SoftRefLRUPolicyMSPerMB(default 1000 ms/MB); on 32 GB — theoretically 9 hours, but in practice much earlier - WeakReference: for WeakHashMap, metadata; cleaned at NEXT collection (doesn’t wait for memory shortage)
- PhantomReference:
get()always null; used ONLY with ReferenceQueue for removal tracking; replacesfinalize() - Cleaner (Java 9+):
finalize()replacement; lambda does NOT have reference to this → no “resurrection”;cleanable.clean()for manual cleanup - Reference Handler: high-priority system thread; GC → Pending List → Reference Handler → ReferenceQueue → application polls
- Resurrection: in
finalize()you can assignthisto static field → object “resurrects”; Cleaner cannot resurrect
Common follow-up questions:
- Why can SoftReference on 32 GB live for hours? — Formula: 32 GB × 1000 ms/MB = 9 hours; tuning:
-XX:SoftRefLRUPolicyMSPerMB=100→ more aggressive - Why does PhantomReference.get() always return null? — Specifically designed: object almost removed, reference no longer needed; only ReferenceQueue for tracking
- How is Cleaner better than finalize()? — Cleaner lambda does NOT have reference to this → impossible to resurrect object; finalize() can assign
this→ resurrection - Why is Reference Handler asynchronous? — Doesn’t block GC; GC puts object in Pending List; Reference Handler processes later → application polls ReferenceQueue
Red flags (DO NOT say):
- “SoftReference is cleaned immediately after Strong reference removed” — cleaned ONLY on OOM threat
- “PhantomReference allows getting the object” —
get()always null; only ReferenceQueue - “finalize() is a normal way to clean resources” — deprecated (Java 9+), unpredictable, can resurrect object
Related topics:
- [[5. When does an object become eligible for GC]]
- [[25. What are GC roots]]
- [[27. Can you manually invoke GC]]
- [[6. What is a memory leak in Java]]
- [[4. What is Garbage Collection]]