Progress
🌍
Why does this topic matter?
Memory management is invisible — until it crashes your program. Understanding where a variable lives (stack vs heap) explains every "surprising" Java behavior you will ever encounter: why primitives are copied but objects are shared, why passing an object to a method can change it while passing an int never can, and why a missing null check causes a NullPointerException. This knowledge also directly impacts how you reason about the space complexity of your algorithms.

📖 Before We Start — The Big Picture

Every Java program runs inside the Java Virtual Machine (JVM) — a software layer that sits between your code and the real hardware. The JVM manages all memory on your behalf, splitting it into distinct regions, each with a specific job.

Stack = a small, fast notepad on your desk. Each method call writes its local variables here. When the method returns, the page is torn off and thrown away. Heap = a large warehouse. Every object you create with new is stored here and stays until nobody is referencing it anymore. The Garbage Collector is the warehouse cleaner — it periodically sweeps away objects nobody is using.

🔗
How it connects: Lecture 1 taught you what types exist. This lecture explains where they live in memory. Lecture 3 (OOP) builds on this — every object you create goes onto the heap, and understanding that is why == compares addresses, not values.

🏗 JVM Architecture

📌
The Mental Model: The JVM manages all memory for your program in distinct regions. Understanding these regions explains why Java behaves differently from C/C++ and helps you reason about performance and bugs.
┌──────────────────────── JVM MEMORY ────────────────────────┐ │ HEAP (all threads share this) │ │ ┌───────────────┐ ┌───────────────────┐ ┌──────────┐ │ │ │ YOUNG GEN │ │ OLD GEN │ │ METASPACE│ │ │ │ Eden |S0|S1 │ │ (long-lived objs) │ │ Classes │ │ │ │ new objs │ │ tenured ≥15 GCs │ │ Statics │ │ │ └───────────────┘ └───────────────────┘ └──────────┘ │ ├────────────────────────────────────────────────────────────┤ │ STACK (one per thread — holds method frames) │ │ ┌───────────────┐ ┌───────────────┐ ┌───────────┐ │ │ │ Frame:main │ │ Frame:sort │ │ Frame:cmp │ ← TOP │ │ │ local vars │ │ local vars │ │ a,b,ret │ │ │ └───────────────┘ └───────────────┘ └───────────┘ │ └────────────────────────────────────────────────────────────┘

Stack vs Heap Quick Reference

Property Stack Heap
What lives here Primitives, reference variables (pointer itself), frames All objects, arrays
Size Small ~1 MB/thread Large (configured via -Xmx)
Thread safety ✅ Private per thread ❌ Shared — needs sync
Speed ⚡ Very fast (LIFO pointer) Slower (GC pressure)
Error StackOverflowError OutOfMemoryError
☕ Java · Memory Layout
int x = 42;               // x lives on STACK (primitive)
String s = "hi";          // s (ref) on STACK → String object on HEAP
int[] arr = {1,2,3};    // arr (ref) on STACK → int[3] on HEAP

// Reference copy ≠ object copy!
int[] a = {1,2,3};
int[] b = a;           // b points to SAME array
b[0] = 99;
System.out.println(a[0]); // → 99! Same heap array

// Deep copy needed for independence:
int[] c = Arrays.copyOf(a, a.length);

🔡 String Pool & Interning

☕ Java · String Pool
String a = "hello";           // Pool["hello"] → 0xAAA
String b = "hello";           // same Pool object 0xAAA
System.out.println(a == b);      // → true

String c = new String("hello");// bypasses pool → new heap obj
System.out.println(a == c);      // → false (different refs)
System.out.println(a.equals(c)); // → true  (same content)

String d = c.intern();          // force into pool
System.out.println(a == d);      // → true

// RULE: ALWAYS use .equals() for string comparison. Never ==.

🗑 Garbage Collection

💡
Generational Hypothesis: Most objects die young. GC exploits this by collecting the small Young Generation frequently (Minor GC — fast) and the Old Generation rarely (Major GC — slow Stop-the-World).

🗂 JCF Masterclass

Class Backing get add/put remove Order
ArrayList Object[] O(1) O(1)* O(n) Insertion
LinkedList Doubly linked O(n) O(1) ends O(1) ends Insertion
ArrayDeque Circular array O(1) ends O(1)* O(1) ends Insertion
PriorityQueue Binary heap O(1) peek O(log n) O(log n) Priority
HashSet HashMap O(1) avg O(1) avg None
TreeSet Red-Black O(log n) O(log n) O(log n) Sorted
HashMap Array+list/tree O(1) avg O(1) avg O(1) avg None
LinkedHashMap HashMap+list O(1) avg O(1) avg O(1) avg Insertion
TreeMap Red-Black O(log n) O(log n) O(log n) Sorted key

HashMap Internals

🔍
Bucket index = hash(key) & (n-1). Collisions form a linked list per bucket. When chain length ≥ 8 it treeifies to a Red-Black Tree (O(log n) worst case). Doubles capacity when size > capacity × 0.75.

When to Use Which

Need Use
Frequency count HashMap<T,Integer> + getOrDefault
Visited set (BFS/DFS) HashSet<T>
Min/Max always available PriorityQueue (min-heap default)
Stack or Queue ArrayDeque (faster than Stack class)
LRU Cache LinkedHashMap with accessOrder=true
Floor/Ceiling key queries TreeMap

💪 Practice Problems

P01 · Hashing
Group Anagrams
MediumAmazonGoogleHashMap
P02 · HashMap+Heap
Top K Frequent Elements
MediumAmazonFacebookHashMap+MinHeap
P03 · LinkedHashMap
LRU Cache
HardAmazonMicrosoftLinkedHashMap
P04 · HashMap Lookup
Two Sum
EasyAmazonGoogleHashMap
P05 · Stack
Valid Parentheses
EasyMetaGoogleStack
P06 · Two-Stack Design
Min Stack
MediumAmazonDesign
P07 · HashSet
Longest Consecutive Sequence
MediumGoogleMetaHashSet

📝 Assignment

📋
Lecture 2 Assignment
25+ problems: JVM memory quiz, String pool traps, HashMap patterns, LRU Cache, Top-K, Group Anagrams, and heap operation practice.

Open Assignment →

✅ Completion Checklist

I can draw the JVM memory layout from scratch (Stack, Eden, S0/S1, Old Gen, Metaspace)
I know what lives on Stack vs Heap and can trace any code snippet
I know why new String("x") == "x" is false
I can explain GC eligibility and what a memory leak looks like in Java
I know time complexity of HashMap, TreeMap, PriorityQueue, ArrayDeque
I understand how HashMap computes bucket index and handles collisions
I can implement LRU Cache using LinkedHashMap in under 10 min
I can solve Top-K using HashMap + PriorityQueue
I know when to use TreeMap.floorKey() vs HashMap
I understand the treeify threshold (8) and load factor (0.75) in HashMap
🧠
You're ready for Topic 3: OOP & Collections
You've mastered Java Memory — the JVM Stack & Heap, garbage collection, and String interning. OOP is where Java's power truly unlocks. Get ready for inheritance, polymorphism, generics, and Java Collections.
← Topic 1: Java FundamentalsTopic 3: OOP & Collections →