Back to Memory Management & GC
Q18Question 18 of 21

What is shallow heap vs retained heap in heap dump analysis?

Key Concepts
  • Shallow: just the object (header + fields)
  • Retained: the object + everything only IT references
  • Retained heap shows the true cost of keeping an object alive
  • Eclipse MAT shows both in the Dominator Tree
  • Understanding this concept is essential for Java interviews at senior level

Definition

Shallow heap: memory of the object itself. Retained heap: total memory freed if this object were GC'd (includes all exclusively referenced objects).

- Shallow: just the object (header + fields)\n- Retained: the object + everything only IT references\n- Retained heap shows the true cost of keeping an object alive\n- Eclipse MAT shows both in the Dominator Tree

Understanding the Concepts

What is shallow heap vs retained heap in heap dump analysis?

shallow heap vs retained heap in heap dump analysis is an important concept in Java that every banking application developer should understand. In the context of National Bank of India's transaction processing system, Rajesh uses this concept regularly when building reliable financial services.

- Shallow: just the object (header + fields)\n- Retained: the object + everything only IT references\n- Retained heap shows the true cost of keeping an object alive\n- Eclipse MAT shows both in the Dominator Tree

JAVA
package com.bank.core;

import java.math.BigDecimal;

public class ConceptDemo {
    private String accountId = "SAV2001";
    private BigDecimal balance = new BigDecimal("50000.00");

    public static void main(String[] args) {
        ConceptDemo demo = new ConceptDemo();
        System.out.println("Account: " + demo.accountId);
        System.out.println("Balance: " + demo.balance);
    }
}
TEXT
Account: SAV2001
Balance: 50000.00

Why does shallow heap vs retained heap in heap dump analysis matter?

Understanding shallow heap vs retained heap in heap dump analysis is critical for building production-grade banking applications. Without this knowledge, developers may write code that behaves unexpectedly under load or fails in edge cases.

At National Bank of India, Pankaj emphasizes that every developer on the team must understand this concept because it directly affects the reliability and performance of the transaction processing pipeline.

  • It affects how the JVM manages memory and resources.
  • It influences the behavior of concurrent banking transactions.
  • It determines how objects are created, stored, and cleaned up.
  • It impacts application performance under high transaction volumes.
JAVA
package com.bank.service;

import java.math.BigDecimal;

public class TransferService {
    public boolean transfer(String fromAccount, String toAccount, BigDecimal amount) {
        // This demonstrates why understanding the concept matters
        BigDecimal fromBalance = getBalance(fromAccount);
        if (fromBalance.compareTo(amount) >= 0) {
            debit(fromAccount, amount);
            credit(toAccount, amount);
            System.out.println("Transferred " + amount + " from " + fromAccount + " to " + toAccount);
            return true;
        }
        System.out.println("Insufficient balance in " + fromAccount);
        return false;
    }

    private BigDecimal getBalance(String accountId) {
        return new BigDecimal("100000.00");
    }
    private void debit(String accountId, BigDecimal amount) { /* debit logic */ }
    private void credit(String accountId, BigDecimal amount) { /* credit logic */ }
}

How does shallow heap vs retained heap in heap dump analysis work internally?

When the JVM processes this concept, it follows a specific internal mechanism. The JVM specification defines the behavior precisely, which ensures consistent results across different JVM implementations.

JAVA
package com.bank.internal;

import java.math.BigDecimal;

public class InternalBehaviorDemo {
    public static void main(String[] args) {
        // Step 1: Object creation on the heap
        BigDecimal balance = new BigDecimal("75000.00");

        // Step 2: JVM processes the operation
        BigDecimal interest = balance.multiply(new BigDecimal("0.045"));

        // Step 3: Result is a new immutable object
        System.out.println("Interest: " + interest);
        System.out.println("Original unchanged: " + balance);
    }
}
TEXT
Interest: 3375.000
Original unchanged: 75000.00

How is this used in a banking application?

In National Bank of India's core banking system, Rajesh applies this concept in several places:

  • Account processing: When creating and managing customer accounts.
  • Transaction logging: When recording financial transactions for audit.
  • Interest calculation: When computing daily interest on savings accounts.
  • Statement generation: When building monthly statements for customers like Priya.
JAVA
package com.bank.model;

import java.math.BigDecimal;
import java.time.LocalDateTime;

public class Transaction {
    private final String transactionId;
    private final String fromAccount;
    private final String toAccount;
    private final BigDecimal amount;
    private final LocalDateTime timestamp;

    public Transaction(String txnId, String from, String to, BigDecimal amount) {
        this.transactionId = txnId;
        this.fromAccount = from;
        this.toAccount = to;
        this.amount = amount;
        this.timestamp = LocalDateTime.now();
    }

    @Override
    public String toString() {
        return "TXN[" + transactionId + "] " + fromAccount + " -> " + toAccount + " : " + amount;
    }

    public static void main(String[] args) {
        Transaction txn = new Transaction("TXN-001", "SAV2001", "CUR3001", new BigDecimal("5000.00"));
        System.out.println(txn);
    }
}
TEXT
TXN[TXN-001] SAV2001 -> CUR3001 : 5000.00

What are common mistakes?

A common mistake is not understanding the full implications of this concept in a banking production environment.

Wrong approach:

JAVA
package com.bank.service;

public class WrongApproach {
    public void processAccount() {
        // WRONG: using double for money
        double balance = 10000.50;
        double fee = 0.1;
        double result = balance - fee;
        System.out.println(result);  // 10000.4 (precision lost!)
    }
}

Correct approach:

JAVA
package com.bank.service;

import java.math.BigDecimal;

public class CorrectApproach {
    public void processAccount() {
        // CORRECT: using BigDecimal for money
        BigDecimal balance = new BigDecimal("10000.50");
        BigDecimal fee = new BigDecimal("0.10");
        BigDecimal result = balance.subtract(fee);
        System.out.println(result);  // 10000.40 (exact!)
    }
}

What should a senior engineer know?

A senior engineer should understand the production implications:

  • Performance profiling: Use JFR (Java Flight Recorder) and JMC (Java Mission Control) to measure the impact in production.
  • Thread safety: Consider how this concept interacts with concurrent access in a multi-threaded banking service.
  • JVM tuning: Adjust JVM parameters based on the workload characteristics of the banking application.
  • Monitoring: Set up JMX metrics and alerts in production to detect issues early.
JAVA
package com.bank.monitoring;

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;

public class JvmInfoDemo {
    public static void main(String[] args) {
        RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean();
        System.out.println("JVM: " + runtime.getVmName());
        System.out.println("Uptime: " + runtime.getUptime() + " ms");
        System.out.println("Input args: " + runtime.getInputArguments());
    }
}

What are the edge cases?

JAVA
package com.bank.edge;

import java.math.BigDecimal;

public class EdgeCaseDemo {
    public static void main(String[] args) {
        // Edge case 1: null handling
        String accountId = null;
        System.out.println(accountId == null);  // true

        // Edge case 2: BigDecimal equality
        BigDecimal a = new BigDecimal("10.0");
        BigDecimal b = new BigDecimal("10.00");
        System.out.println(a.equals(b));       // false (different scale)
        System.out.println(a.compareTo(b) == 0); // true (same value)

        // Edge case 3: Integer caching
        Integer x = 127;
        Integer y = 127;
        System.out.println(x == y);  // true (cached)
        Integer p = 128;
        Integer q = 128;
        System.out.println(p == q);  // false (not cached)
    }
}
TEXT
true
false
true
true
false

What are common interview follow-up questions?

  • How does this concept interact with garbage collection?
  • What tools would you use to debug issues related to this concept?
  • How does this behave differently in Java 8 vs Java 17+?
  • What are the thread safety implications?
  • How would you optimize this for a high-throughput banking system?

Key Takeaway

Shallow heap: memory of the object itself. Retained heap: total memory freed if this object were GC'd (includes all exclusively referenced objects).\n\n

Remember one sentence: In heap-dump analysis, what is the difference between shallow heap and retained heap, and why do you sort by retained heap to find memory accumulators is fundamental knowledge for Java interviews and production banking work.

---

Share
Use ← → arrow keys to navigate