Master Core Java Programming From Scratch

Clear, interactive, and structured coding lessons designed for absolute beginners.

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.

Java
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.

Concept
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.

Java
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.

Java
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.

Java
Student student = null;
Important: Attempting to access an instance member through a null reference can cause a NullPointerException.

Primitive Variables and Object References

Primitive variables directly represent primitive values, while reference variables refer to objects.

Java
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.

Java
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.

Java
String a = "CIIT";

String b = "CIIT";

System.out.println(a == b);
Output
true

Both variables can refer to the same interned String object when the same literal is used.

String Created with new

Java
String a = "CIIT Institute";

String b = new String("CIIT Institute");

System.out.println(a == b);
Output
false

The new expression creates a separate String object. For content comparison, use .equals().

Memory During Method Calls

Java
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.

Java
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.

Note: Memory errors are generally application or environment problems and should be investigated using profiling, monitoring, heap analysis, and appropriate JVM configuration.

Garbage Collection

Java automatically reclaims heap memory occupied by objects that are no longer reachable.

Concept
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.

Example
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.