Back to JVM Internals: Advanced
Q9Question 9 of 10

What are the four reference types in Java?

Key Concepts
  • Strong reference: normal reference – object is never GC'd while reachable
  • Soft reference (SoftReference): GC'd when memory is low – ideal for caches
  • Weak reference (WeakReference): GC'd at the next GC cycle – used by WeakHashMap
  • Phantom reference (PhantomReference): enqueued after the object is finalized – for cleanup actions
  • Understanding this concept is essential for Java interviews at senior level

Definition

Strong (never GC'd while reachable), Soft (GC'd when memory is low), Weak (GC'd at next GC), Phantom (post-finalization cleanup). Each is weaker than the previous.

Four reference strengths:

  • Strong: Account a = new Account() – GC never touches it while a exists.
  • Soft: SoftReference – GC collects only when heap is running low. Good for caches.
  • Weak: WeakReference – GC collects at the next collection cycle. Used by WeakHashMap.
  • Phantom: PhantomReference – object already finalized, used for post-mortem cleanup via a ReferenceQueue.

Strong: a customer actively holding their passbook (never taken away). Soft: a passbook in the "might need" pile (returned when space is tight). Weak: a passbook in the outgoing tray (collected next cleanup). Phantom: a passbook already shredded, with just a notification left.

Understanding the Concepts

Usage examples

JAVA
// Strong: normal reference
Account a = new Account("SAV2001");
// a is strong – GC will not touch the Account

// Soft: cache
SoftReference<byte[]> cache = new SoftReference<>(new byte[10_000_000]);
byte[] data = cache.get();  // non-null until memory pressure

// Weak: auto-cleanup map
WeakReference<Account> weak = new WeakReference<>(new Account("TEMP"));
System.gc();
System.out.println(weak.get());  // likely null after GC

// Phantom: cleanup notification
ReferenceQueue<Account> queue = new ReferenceQueue<>();
PhantomReference<Account> phantom = new PhantomReference<>(new Account("TEMP"), queue);
// phantom.get() always returns null
// After GC, phantom is enqueued in the queue → trigger cleanup

Comparison table

| Type | GC'd when | get() returns | Use case |
|---|---|---|---|
| Strong | Never (while reachable) | The object | Normal references |
| Soft | Memory is low | Object or null | Memory-sensitive caches |
| Weak | Next GC cycle | Object or null | WeakHashMap, listeners |
| Phantom | After finalization | Always null | Post-mortem cleanup |

What should a senior engineer know?

  • Caffeine cache uses soft/weak references for eviction.
  • WeakHashMap uses weak keys – entries are automatically removed when the key is GC'd.
  • Cleaner (Java 9+) is the modern replacement for finalize(), built on phantom references.
  • Do not use soft references as a substitute for proper cache eviction. The JVM's eviction timing is unpredictable.

What are common mistakes?

A common mistake is not understanding the concept fully before using it in production banking applications.

Wrong approach:

JAVA
package com.bank.service;

public class TransferService {
    public void transfer(String fromAccount, String toAccount, double amount) {
        // WRONG: using double for money
        double balance = getBalance(fromAccount);
        balance = balance - amount;
    }
    private double getBalance(String id) { return 10000.0; }
}

Correct approach:

JAVA
package com.bank.service;

import java.math.BigDecimal;

public class TransferService {
    public void transfer(String fromAccount, String toAccount, BigDecimal amount) {
        // CORRECT: using BigDecimal for money
        BigDecimal balance = getBalance(fromAccount);
        balance = balance.subtract(amount);
    }
    private BigDecimal getBalance(String id) { return new BigDecimal("10000.00"); }
}

Always use BigDecimal for monetary calculations in banking systems to avoid floating-point precision errors.

What are the edge cases?

Edge cases can cause unexpected behavior in banking applications. Here are some to watch for.

JAVA
package com.bank.edge;

public class EdgeCaseDemo {
    public static void main(String[] args) {
        // Edge case 1: null handling
        String accountId = null;
        try {
            System.out.println(accountId.length());
        } catch (NullPointerException e) {
            System.out.println("Null account ID");
        }

        // Edge case 2: empty vs null
        String emptyId = "";
        System.out.println(emptyId.isEmpty());  // true
        System.out.println(emptyId == null);     // false

        // Edge case 3: boundary values
        java.math.BigDecimal zero = java.math.BigDecimal.ZERO;
        java.math.BigDecimal negativeBalance = new java.math.BigDecimal("-0.01");
        System.out.println(zero.compareTo(negativeBalance) > 0);  // true
    }
}
TEXT
Null account ID
true
false
true

Always test with null values, empty strings, boundary values, and negative amounts in banking applications.

What are common interview follow-up questions?

Interviewers often follow up with these related questions:

  • How does this concept apply to a high-throughput banking transaction system?
  • What are the performance implications in a production environment?
  • How would you debug issues related to this concept?
  • What tools would you use to monitor this in production?
  • How does this behave differently in Java 8 vs Java 17+?

When answering follow-up questions, always relate your answer back to practical experience. For example, at National Bank of India, Rajesh debugged a production issue related to this concept by using JFR recordings and heap dumps. Providing concrete examples from banking systems shows the interviewer that you understand both the theory and the practice.

Visual Overview

DIAGRAM
  Reference strength: Strong > Soft > Weak > Phantom

  Strong:  object reachable → never GC'd
  Soft:    memory OK → kept; memory low → GC'd
  Weak:    next GC → collected
  Phantom: already dead → cleanup notification via ReferenceQueue

Key Takeaway

Java has four reference types with decreasing strength. Strong references keep objects alive. Soft references are for memory-sensitive caches. Weak references are collected at the next GC. Phantom references enable post-mortem cleanup.

One sentence to remember: Strong never GC'd, Soft when memory low, Weak next GC, Phantom after death.

---

Share
Use ← → arrow keys to navigate