Stack

  • Purpose: Stores method calls, local variables, and references.
  • Order: LIFO (Last-In-First-Out).
  • Lifetime: Data is automatically popped off when a method returns.
  • Speed: Very fast, but limited in size.
  • What goes here:
    • Primitive types (int, double, boolean, etc.)
    • References (pointers) to objects in the heap

Heap

  • Purpose: Stores objects created with new.

  • Lifetime: Exists until no reference points to it → then garbage collected.

  • Speed: Slower than stack, but much larger and flexible.

  • What goes here:

    • Objects (new Person(), new String("Hello"))

    • Class-level variables (static fields)


📊 Diagram: Stack vs Heap

                High Memory Address
                +-------------------+
                |                   |
                |       Stack       |  <-- grows downward (new frames push down)
                |   ----------------|
                |   main() frame    |
                |     int x=10      |
                |     ref -> 0x1a2b |
                |   ----------------|
                |   doStuff() frame |
                |     int y=20      |
                |                   |
                +-------------------+
                |                   |
                |       Free         |  (unused space between stack & heap)
                |                   |
                +-------------------+
                |                   |
                |       Heap        |  <-- grows upward (new objects allocate up)
                |   ----------------|
                | Person@0x1a2b     |
                |   name="Jonas"    |
                |   age=25          |
                |   ----------------|
                | int[]@0x2c3d      |
                |   [1,2,3,4,5]     |
                |                   |
                +-------------------+
                Low Memory Address

+----------------------+         +----------------------------+
|        Stack         |         |            Heap            |
+----------------------+         +----------------------------+
| main() frame         |   --->  | Person@0x1a2b (object)     |
|   - x = 10           |         | name = "Jonas"             |
|   - ref -> 0x1a2b ---+-------> | age = 25                   |
+----------------------+         +----------------------------+
| doSomething() frame  |         | Array@0x2c3d (int[5])      |
|   - y = 20           |         | [1,2,3,4,5]                |
+----------------------+         +----------------------------+
  • The stack holds local variables and references.

  • The heap holds the actual objects.


💻 Code Example

public class MemoryDemo {
    public static void main(String[] args) {
        int number = 42;                     // stored in stack
        Person person = new Person("Jonas"); // reference in stack, object in heap
        person.sayHello();
    }
}
 
class Person {
    String name;  // stored in heap with the object
 
    Person(String name) {
        this.name = name;
    }
 
    void sayHello() {
        String greeting = "Hello " + name; // greeting reference in stack
        System.out.println(greeting);      // String object in heap
    }
}
  • number (primitive) lives in the stack.

  • person (reference) lives in the stack, but the Person object itself lives in the heap.

  • name field is in the heap, because it’s part of the object.

  • greeting (reference) is in the stack, but the new String object it points to is in the heap.


🌐 Quick Analogy

  • Stack = A stack of plates in a cafeteria. Only the top plate can be added/removed.

  • Heap = A big pile of boxes in a warehouse. You can store things anywhere, but need addresses (references) to find them.