Understanding JVM Memory Architecture and Garbage Collection

JVM Memory Layout

The Java Virtual Machine organizes its memory into several distinct regions during program execution, each with specific purposes and lifecycles.

1. Program Counter Register

Also known as the PC register, this area holds the address of the next instruction to execute for each thread. In a multi-threaded environment, each thread maintains its own independent counter to ensure correct execution flow upon context switching. This region is thread-local and never causes OutOfMemoryError.

2. Java Virtual Machine Stack

Each method invocation creates a stack frame containing:

  • Local variables table: stores primitive values directly and object references as heap addresses
  • Operand stack: used for expression evaluation and computation
  • Runtime constant pool reference: links to class constants
  • Return address: tracks where execution should resume after method completion

Stack frames are managed automatically by the JVM. Stack overflow occurs when recursion exceeds limits, while out-of-memory errors happen during stack expansion failures.

3. Native Method Stack

Similar to the JVM stack but serves native methods (implemented in C/C++). HotSpot combines this with the JVM stack for simplicity.

4. Heap Memory

The primary storage area for object instances and arrays. All threads share this region. The garbage collector manages memory allocation here, handling automatic deallocation through collection cycles.

5. Method Area

Shared across all threads, storing:

  • Class metadata
  • Static variables
  • Runtime constant pool

This area also reports OutOfMemoryError when insufficient space exists.

Variable Storage Locations

Variables are categorized as:

  • Instance variables: stored in heap memory, unique per object instance
  • Static variables: stored in method area, shared among all class instances
  • Local variables: stored in stack frames, limited to method scope
  • Constants: stored in runtime constant pool, including final variables and string literals

Garbage Collection Mechanisms

Object Reachability Analysis

Rather than counting references, modern JVMs use reachability analysis starting from GC roots:

  • Local variables in active stack frames
  • Static fields in loaded classes
  • Constant references in method areas
  • JNI references in native methods

Objects unreachable from these root are eligible for collection.

Garbage Collection Process

Unreachable objects undergo two-step marking:

  1. First marking: identify objects with no GC root references
  2. Filtering: determine if finalize() should be called

Objects can override finalize() to prevent deletion, but this mechanism executes at most once per object.

public class FinalizeEscapeDemo {
    public static FinalizeEscapeDemo SAVE_HOOK = null;
    
    public void isAlive() {
        System.out.println("still alive");
    }
    
    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        SAVE_HOOK = this;
    }
    
    public static void main(String[] args) throws Throwable {
        SAVE_HOOK = new FinalizeEscapeDemo();
        
        SAVE_HOOK = null;
        System.gc();
        Thread.sleep(500);
        
        if (SAVE_HOOK != null) {
            SAVE_HOOK.isAlive();
        } else {
            System.out.println("dead");
        }
        
        SAVE_HOOK = null;
        System.gc();
        Thread.sleep(500);
        
        if (SAVE_HOOK != null) {
            SAVE_HOOK.isAlive();
        } else {
            System.out.println("dead again");
        }
    }
}

Collection Algorithms

Mark-Sweep Algorithm

Basic approach: mark unreachable objects then sweep to reclaim space. Creates fragmentation issues.

Copying Algorithm

Divides memory into two spaces. Copies live objects to the other space when one fills up. Eliminates fragmentation but halves available memory.

Mark-Compact Algorithm

Marks objects, then moves survivors to one side before compacting memory. Prevents fragmentation but requires moving data.

Generational Collection

Separates heap into young and old ganerations based on objeect lifespan:

  • Young generation uses copying algorithm due to high turnover
  • Old generation uses mark-compact due to low turnover

Typical ratio: Eden:Survivor1:Survivor2 = 8:1:1

Tags: JVM memory-management garbage-collection java runtime

Posted on Wed, 16 Sep 2026 16:07:56 +0000 by redd