Memory Management in Java
โก Smart Summary
Memory Management in Java explains how the JVM divides runtime memory across Stack, Heap, Code, and Static regions, how object references flow during method calls, and how the Garbage Collector reclaims unreachable objects so applications stay stable and free of memory leaks.

What is Stack Memory in Java?
Stack memory in Java is the region of JVM memory that stores method frames, local variables, and reference variables for each thread. The Stack is always accessed in Last-In-First-Out order, so the most recently invoked method sits on top, and its local variables are pushed and popped with the frame.
Each thread in the Java Virtual Machine receives its own Stack, which keeps method invocations isolated and thread-safe by design. Primitive locals such as int, boolean, and double live directly inside the frame, while object references stored on the Stack point to objects allocated on the Heap.
What is Heap Memory in Java?
Heap memory is the shared JVM region that holds every Java object and array created with the new operator, along with any reference variables that belong to those objects as instance fields. Unlike the Stack, the Heap is shared across all threads, which is why object access often requires synchronization.
The Heap is the area the Garbage Collector manages. Modern HotSpot JVMs divide the Heap into a Young Generation for short-lived objects and an Old Generation for long-lived objects, with class metadata stored in a separate native region called Metaspace.
Memory Allocation in Java
Memory Allocation in Java is the process by which the JVM sets aside virtual memory regions for variables and instances of classes and structures during program execution. The memory is not allocated to an object at declaration; only a reference is created. The actual object allocation happens through the new operator, so every object lives on the Heap.
The Java memory allocation is divided into the following sections:
- Heap
- Stack
- Code
- Static
This division of memory is required for effective management of the runtime.
- The Code section contains your compiled bytecode.
- The Stack section stores methods, local variables, and reference variables.
- The Heap section contains objects and may also contain reference variables held as instance fields.
- The Static section holds static data and static methods shared across all instances.
Difference between Local and Instance Variable
Understanding where each kind of variable lives in the JVM helps explain Stack and Heap behavior. An instance variable is declared inside a class but outside any method, and it lives on the Heap as part of its object.
class Student{ int num; // num is instance variable public void showData{}
A local variable is declared inside a method, including method arguments, and lives on the Stack inside the active frame.
public void sum(int a){ int x = a + 3; // a, x are local variables }
Difference between Stack and Heap
The Stack and the Heap solve different problems inside the JVM. The Stack gives each thread fast, deterministic allocation for short-lived data tied to method scope, while the Heap provides a shared region for long-lived objects that any thread can reference. The short video below summarizes the contrast before the walkthrough that follows.
Click here if the video is not accessible
To see how Stack and Heap cooperate, consider a main method that calls method m1.
public void m1{ int x = 20; }
In the JVM Stack, a frame is created for method m1.
The variable x in m1 is also created in the frame for m1 on the Stack, as shown in the image below.
Method m1 then calls method m2. In the Stack, a new frame is created for m2 on top of the frame for m1.
The local variables b and c are also created inside the frame for m2 on the Stack.
public void m2(int b){ boolean c; }
Next, m2 calls method m3. Again, a frame for m3 is created on the top of the Stack, as shown below.
Now say method m3 creates an object for class Account, which has two instance variables int p and int q.
class Account { int p; int q; }
Here is the code for method m3.
public void m3(){ Account ref = new Account(); // more code }
The statement new Account() creates an object of Account on the Heap.
The reference variable ref is created on the Stack inside the frame for m3.
The assignment operator makes the reference variable point to the object on the Heap.
Once the method completes execution, control returns to the calling method, which in this case is method m2.
The frame for method m3 is flushed out of the Stack.
Since the reference variable no longer points to the object on the Heap, that object becomes eligible for garbage collection.
Once method m2 has finished, it is popped off the Stack and all its variables become unavailable. The same happens for method m1, and eventually control returns to the main method.
What if an object holds another reference as its instance variable?
public static void main(String args[]) { A parent = new A(); // more code } class A { B child = new B(); int e; } class B { int c; int d; }
In this case, the reference variable child lives on the Heap as part of the A object, and in turn points to its own B object, as shown below.
What is Garbage Collection in Java?
Garbage Collection in Java is the process by which the JVM performs memory management automatically. The Garbage Collector finds objects that are no longer reachable from any live reference and reclaims their memory. Dynamic memory allocation happens through the new operator, and the memory stays allocated until the program no longer holds any reference to the object.
When no references remain, the object is considered no longer needed, and the memory it occupies can be reclaimed. There is no explicit need to destroy an object because Java handles the deallocation automatically through the Garbage Collector.
The technique behind this is known as Garbage Collection. Programs that fail to release memory eventually crash when nothing remains to allocate. Such programs are said to have memory leaks. Garbage Collection in Java runs automatically across the lifetime of the program, which removes the burden of manual deallocation and reduces the risk of leaks.
In C, by contrast, the programmer is responsible for releasing memory allocated dynamically through the free() function. This is where Java memory management offers a strong advantage.
Modern HotSpot JVMs ship several Garbage Collectors tuned for different workloads. The default G1 Garbage Collector targets balanced throughput and pause times on multi-gigabyte heaps. ZGC and Shenandoah aim for sub-millisecond pauses on very large heaps, which makes them attractive for latency-sensitive services. Choosing the right collector and tuning the Young Generation, Old Generation, and Metaspace sizes is a core skill for Java performance work.
Note: All objects are created in the Heap section of memory, which is the region the Garbage Collector manages.
Example: To Learn Garbage Collector Mechanism in Java
This walkthrough shows when references become eligible for Garbage Collection inside a simple program.
Step 1) Copy the following code into an editor.
class Student{ int a; int b; public void setData(int c,int d){ a=c; b=d; } public void showData(){ System.out.println("Value of a = "+a); System.out.println("Value of b = "+b); } public static void main(String args[]){ Student s1 = new Student(); Student s2 = new Student(); s1.setData(1,2); s2.setData(3,4); s1.showData(); s2.showData(); //Student s3; //s3=s2; //s3.showData(); //s2=null; //s3.showData(); //s3=null; //s3.showData(); } }
Step 2) Save, compile, and run the code. As shown in the diagram, two objects and two reference variables are created.
Step 3) Uncomment lines 20, 21, and 22. Save, compile, and run the code.
Step 4) As shown in the diagram below, two reference variables now point to the same object.
Step 5) Uncomment lines 23 and 24. Save, compile, and run the code.
Step 6) As shown below, s2 becomes null, but s3 still points to the object, so the object is not yet eligible for Garbage Collection.
Step 7) Uncomment lines 25 and 26. Save, compile, and run the code.
Step 8) At this point, no references point to the object, so it becomes eligible for Garbage Collection. The Garbage Collector removes it from memory, and there is no way to retrieve it.
How to Delete an Object in Java?
Java does not provide a manual delete operator, so the standard approach is to remove every reference to the object so the Garbage Collector can reclaim it.
1) To make an object eligible for Garbage Collection, assign every reference variable that points to it to null.
2) Primitive types are not objects, so they cannot be assigned null. Their storage is reclaimed automatically when the surrounding Stack frame is popped.


















