Lesson Completion
Back to course

Reference Types: Strong, Soft, Weak, and Phantom References

Beginner
12 minutes4.8Java

1. The Hook (The "Byte-Sized" Intro)

  • In a Nutshell: Java has 4 reference types: (1) Strong (normal, Object obj = new Object()—never GC'd while reachable), (2) Soft (SoftReference<T>—GC'd before OOM, for caches), (3) Weak (WeakReference<T>—GC'd at next cycle, WeakHashMap), (4) Phantom (PhantomReference<T>—cleanup actions, post-finalization). Weak = "I want it, but GC can take it". Soft = "Keep it if memory available". Phantom = "Tell me after GC'd".
  • Use: Soft for caches, Weak for metadata, Phantom for cleanup!

Think of library books. Strong = you own the book (never taken). Soft = library keeps popular books (discards if space needed). Weak = you borrowed, library can reclaim anytime. Phantom = notification when book destroyed (for inventory update)!


2. Conceptual Clarity (The "Simple" Tier)

💡 The Analogy

  • Strong: Owned property (yours)
  • Soft: Lease with option (kept if space)
  • Weak: Temporary pass (revoked anytime)
  • Phantom: Demolition notice (cleanup hook)

3. Technical Mastery (The "Deep Dive")

Reference Types Comparison

TypeGC BehaviorUse CaseExample
StrongNever GC'd (while reachable)Normal objectsObject obj = new Object()
SoftGC'd before OOMMemory-sensitive cachesSoftReference<Image> cache
WeakGC'd at next cycleCanonicalizing mappingsWeakHashMap<Key, V>
PhantomAfter finalizationPost-mortem cleanupPhantomReference<Resource>

4. Interactive & Applied Code

java
import java.lang.ref.*; import java.util.*; public class ReferenceTypesDemo { public static void main(String[] args) throws Exception { demonstrateStrong(); demonstrateSoft(); demonstrateWeak(); demonstratePhantom(); demonstrateWeakHashMap(); } // 1. Strong reference (default) static void demonstrateStrong() { System.out.println("=== STRONG REFERENCE ==="); Object obj = new Object(); // Strong reference System.gc(); // obj NEVER GC'd while reachable System.out.println("Strong ref: " + obj); obj = null; // Remove reference System.gc(); // NOW eligible for GC } // 2. Soft reference (cache-friendly) static void demonstrateSoft() throws Exception { System.out.println("\n=== SOFT REFERENCE ==="); Object obj = new Object(); SoftReference<Object> softRef = new SoftReference<>(obj); obj = null; // Remove strong reference System.out.println("Before GC: " + softRef.get()); // Still available System.gc(); Thread.sleep(100); // May still be available (GC keeps if memory available) System.out.println("After GC: " + softRef.get()); // Soft refs cleared only before OutOfMemoryError // Good for caches! list<SoftReference<Image>> imageCache = ... } // 3. Weak reference (weak connection) static void demonstrateWeak() throws Exception { System.out.println("\n=== WEAK REFERENCE ==="); Object obj = new Object(); WeakReference<Object> weakRef = new WeakReference<>(obj); System.out.println("Before null: " + weakRef.get()); // Available obj = null; // Remove strong reference System.gc(); Thread.sleep(100); // Weak ref cleared at next GC System.out.println("After GC: " + weakRef.get()); // null } // 4. Phantom reference (cleanup hook) static void demonstratePhantom() throws Exception { System.out.println("\n=== PHANTOM REFERENCE ==="); ReferenceQueue<Object> queue = new ReferenceQueue<>(); Object obj = new Object(); PhantomReference<Object> phantomRef = new PhantomReference<>(obj, queue); System.out.println("get() always null: " + phantomRef.get()); // Always null! obj = null; // Remove strong reference System.gc(); Thread.sleep(100); // Check queue for notification Reference<?> ref = queue.poll(); if (ref != null) { System.out.println("Object collected, cleanup now!"); // Perform cleanup ref.clear(); } } // WeakHashMap demonstration static void demonstrateWeakHashMap() throws Exception { System.out.println("\n=== WEAKHASHMAP ==="); Map<Object, String> weakMap = new WeakHashMap<>(); Object key1 = new Object(); Object key2 = new Object(); weakMap.put(key1, "Value 1"); weakMap.put(key2, "Value 2"); System.out.println("Before: " + weakMap.size()); // 2 key1 = null; // Remove strong reference to key1 System.gc(); Thread.sleep(100); System.out.println("After GC: " + weakMap.size()); // 1 (key1 entry removed!) } } // Real-world example: Image cache class ImageCache { // Soft references: Keep images if memory available private Map<String, SoftReference<Image>> cache = new HashMap<>(); Image getImage(String path) { SoftReference<Image> ref = cache.get(path); if (ref != null) { Image img = ref.get(); if (img != null) { return img; // Cache hit } } // Cache miss: Load image Image img = loadImage(path); cache.put(path, new SoftReference<>(img)); return img; } Image loadImage(String path) { return new Image(path); } } class Image { String path; Image(String path) { this.path = path; } } // Canonical mapping with WeakHashMap class StringPool { private static WeakHashMap<String, WeakReference<String>> pool = new WeakHashMap<>(); static String intern(String s) { WeakReference<String> ref = pool.get(s); if (ref != null) { String cached = ref.get(); if (cached != null) { return cached; // Reuse } } pool.put(s, new WeakReference<>(s)); return s; } }

5. The Comparison & Decision Layer

Ref TypeWhen to Use
StrongNormal objects (default)
SoftMemory-sensitive caches (images, large data)
WeakCanonicalizing mappings, metadata
PhantomPre-mortem cleanup (resource release)

6. The "Interview Corner" (The Edge)

The "Killer" Interview Question: "Soft vs Weak reference?" Answer:

  • Soft: GC'd only before OutOfMemoryError (kept if memory available)
  • Weak: GC'd at next GC cycle (regardless of memory)
java
// Soft: For caches SoftReference<Image> soft = new SoftReference<>(new Image()); System.gc(); soft.get(); // ✅ Likely still available (if memory OK) // Weak: For weak mappings WeakReference<String> weak = new WeakReference<>(new String("Hi")); System.gc(); weak.get(); // ❌ Likely null (GC'd)

Pro-Tip: WeakHashMap use case:

java
// Metadata storage (doesn't prevent GC of keys) WeakHashMap<Object, Metadata> metadata = new WeakHashMap<>(); Object obj = new Object(); metadata.put(obj, new Metadata()); // obj used elsewhere... obj = null; // No more strong refs System.gc(); // Entry automatically removed from WeakHashMap! // Prevents memory leak!

Topics Covered

Java Fundamentals

Tags

#java#programming#beginner-friendly

Last Updated

2025-02-01