Memory Basics in Java
Understand how Java manages memory, including the Stack, Heap, objects, references, and method execution.
How Java Memory Works
When a Java application runs, the JVM manages different runtime memory areas for storing data and executing code.
Two of the most important areas for understanding normal application execution are the Stack and Heap.
Important JVM Memory Areas
| Memory Area | Purpose |
|---|---|
| Heap | Stores objects and arrays created during program execution. |
| Stack | Stores method frames, local variables, and method execution state for each thread. |
| Method Area | Stores class-level runtime information such as class metadata and method information. |
| PC Register | Keeps track of the current JVM instruction for each thread. |
| Native Method Stack | Supports execution of native methods. |
Stack Memory
Each thread has its own JVM stack. Whenever a method is called, a stack frame is created for that method.
public static void main(String[] args) {
int number = 10;
calculate(number);
}
static void calculate(int value) {
int result = value * 2;
System.out.println(result);
}
The main() method has its own stack frame.
Calling calculate() creates another stack frame.
Stack Frame
A stack frame contains information needed to execute a method, including local variables and execution state.
Thread Stack
┌──────────────────────────┐
│ calculate() frame │
│ value = 10 │
│ result = 20 │
├──────────────────────────┤
│ main() frame │
│ number = 10 │
└──────────────────────────┘
Heap Memory
The heap is the runtime memory area from which objects and arrays are allocated.
class Student {
String name;
}
Student student = new Student();
student.name = "Komal";
The new Student() expression creates a
Student object on the heap. The variable
student holds a reference to that object.
References
A reference variable can refer to an object stored in the heap.
Student first = new Student();
first.name = "Samiksha ";
Student second = first;
second.name = "Samadhan";
Both first and second refer to the
same object. Therefore, changing the object through
second is visible through first.
null Reference
A reference can contain null, which means it
does not currently refer to an object.
Student student = null;
null reference can cause a
NullPointerException.
Primitive Variables and Object References
Primitive variables directly represent primitive values, while reference variables refer to objects.
int age = 21;
String name = "Samadhan";
The variable age contains the primitive value
25. The variable name refers to a
String object.
Object Lifetime
An object remains usable while it is reachable through references from the running application.
Student student = new Student();
student.name = "Samiksha";
student = null;
After the reference is cleared, the previously created object may become eligible for garbage collection if no other reachable reference points to it.
String and Memory
Java String literals are commonly stored in the String Pool, which is maintained as part of the heap.
String a = "CIIT";
String b = "CIIT";
System.out.println(a == b);
true
Both variables can refer to the same interned String object when the same literal is used.
String Created with new
String a = "CIIT Institute";
String b = new String("CIIT Institute");
System.out.println(a == b);
false
The new expression creates a separate String
object. For content comparison, use
.equals().
Memory During Method Calls
public class Program {
static int square(int number) {
return number * number;
}
public static void main(String[] args) {
int result = square(5);
System.out.println(result);
}
}
Calling square() creates a new stack frame for
that method. Its local parameter exists within that frame.
After the method returns, its frame is removed.
Stack vs Heap
| Feature | Stack | Heap |
|---|---|---|
| Purpose | Method execution and local state. | Objects and arrays. |
| Ownership | Each thread has its own stack. | Shared JVM runtime memory area. |
| Lifetime | Associated with method/thread execution. | Objects remain while reachable and are later reclaimed. |
| Management | Frames are pushed and popped during execution. | Managed by the JVM and garbage collector. |
StackOverflowError
Excessive nested method calls or uncontrolled recursion can exhaust the thread's stack.
static void callAgain() {
callAgain();
}
Calling this method indefinitely can eventually result in a
StackOverflowError.
OutOfMemoryError
If the JVM cannot allocate enough heap memory for required
objects, it can throw OutOfMemoryError.
Garbage Collection
Java automatically reclaims heap memory occupied by objects that are no longer reachable.
Object created
↓
Object is reachable
↓
References removed
↓
Object becomes eligible
↓
Garbage Collector may reclaim memory
Garbage collection is covered in detail in the next lesson.
Can Java Have Memory Leaks?
Yes. Java provides automatic garbage collection, but an application can still retain references to objects that are no longer logically needed.
Because those objects remain reachable, the garbage collector cannot reclaim them.
static List<Object> cache = new ArrayList<>();
cache.add(new Object());
An unbounded cache that continuously retains objects can consume increasing amounts of memory.
Memory Management Best Practices
- Avoid creating unnecessary objects.
- Release references to objects that are no longer needed when appropriate.
- Avoid unbounded caches and collections.
- Use profiling tools when investigating memory problems.
-
Avoid relying on
System.gc()as a normal memory-management strategy. - Understand object lifetime and reference ownership in long-running applications.
Summary
Java uses managed runtime memory. The stack primarily supports method execution and thread-local state, while the heap stores objects and arrays. Understanding references, object reachability, and garbage collection is essential for writing efficient Java applications.