Operating Systems intermediate LIVE DEMO
♻️

Garbage Collection Mark-Sweep-Compact Visualization

Step through managed-runtime garbage collection: allocation, GC roots, reachability, stop-the-world marking, sweeping, compaction, leaks, and recovery.

garbage collectionmemory managementheapmark-sweepcompactionmemory leakJavavisualization
Interactive Demo

Continue with the guided workspace

Use the paired workspace to connect this guide's mental model with live component state, visible signals, and the outcome each step or scenario is meant to prove.

Garbage collection (GC) is the automated process of managing a program’s dynamic memory allocation. Rather than requiring developers to manually allocate and free memory, managed runtimes (like Java, .NET, or V8) run a background garbage collector.

Mental Model

Understanding GC requires visualizing the heap as an object reference graph rooted in the execution stack. Runtimes trace reachability starting from β€œGC Roots”—such as active stack frames, local variables, or static fieldsβ€”and follow all reference paths. Any object that can be reached from these roots is considered live and must be preserved. Any object that is no longer reachable is dead space, which the collector sweeps and optional compacts to reclaim contiguous memory for future allocations.

Components and Why They Exist

Application Thread

The application thread executes the main user program logic (the mutator) that allocates memory and mutates object references. It performs core program execution while dynamically requesting memory blocks from the heap, transitioning its status badge to paused (red) during stop-the-world collection phases.

GC Roots

GC roots are the starting points for reachability tracing, anchoring live objects via active stack frames, local variables, and static fields. They serve as the trusted set of initial references; any object unreachable from these roots is treated as garbage, while live objects remain visibly linked to the GC Roots card.

Heap Space

The heap space is the dedicated pool of dynamic memory where all objects are allocated and stored during program execution. It manages memory pages, stores object instances, and tracks overall utilization and fragmentation metrics as total usage fills during allocation and drops after sweeping and compaction.

Object Graph

The object graph models the network of references linking parent and child objects in memory. It represents the pointer paths that the garbage collector traverses starting from the roots to determine reachability, shifting node colors from white to green when marked live or to red when identified as unreachable garbage.

Mark Queue

The mark queue tracks the traversal frontier during the marking phase to implement tri-color marking or breadth-first search. It holds references to grey objects that have been discovered but whose outgoing references have not yet been fully scanned, queuing and draining object pointers step by step during the Mark phase.

Sweeper

The sweeper reclaims memory occupied by dead, unreachable objects so the space can be reused for future allocations. It iterates through the heap and returns the address ranges of unmarked objects back to the free list, clearing dead object blocks and leaving behind fragmented free holes.

Compactor

The compactor resolves memory fragmentation so free space stays contiguous rather than scattered in small holes. It shifts surviving objects toward one end of the heap and updates all pointers referencing those moved objects, sliding fragmented survivors together into a clean contiguous block.

Free List

The free list tracks available blocks of heap memory that can be allocated to new objects. It maintains pointers to free memory chunks, handing them to the mutator on allocation and updating its free-block counter as reclaimed memory addresses return from the sweeper.

Leak Root

The leak root illustrates how memory leaks happen in managed runtimes when application code unintentionally retains unused references. It anchors obsolete objects in the reachability graph, preventing the collector from reclaiming them so leaked nodes survive sweep cycles while temporary objects are cleared.

Pause Meter

The pause meter monitors and measures Stop-The-World (STW) pauses to show their impact on application responsiveness. It records the duration and frequency of GC pauses that halt mutator execution, lighting up its status indicator and accumulating pause latency whenever mutator threads are stopped.

Edge Cases and Misconceptions

  • Misconception: Unreferenced objects are freed immediately: In trace-based garbage collection, objects are only reclaimed when a collection cycle runs, not the instant they lose references.
  • Misconception: Managed code cannot leak memory: Runtimes only prevent β€œmemory leaks” in the sense of lost pointers. If a program keeps a reference to an unused object in a static collection, cache, or long-lived listener, it remains reachable and will never be collected.
  • Edge Case: Stop-The-World (STW) Pauses: During tracing and compaction, mutator threads must be stopped. If heap memory is large or object references are complex, these pauses can cause application latency spikes (GC pauses).

Open the Garbage Collection simulator sandbox after the walkthrough when you want to experiment with high allocation, manual GC, leak injection, compaction toggles, and OOM pressure.

Common Questions

Why can a garbage collector not reclaim a memory leak?

A managed-runtime leak is often still reachable from a root or long-lived container, so the collector must preserve it even if the application no longer needs it.

What causes stop-the-world pauses?

Collectors sometimes pause application threads to scan roots, trace references, or move objects while maintaining a consistent heap view.

What is the difference between sweeping and compaction?

Sweeping marks memory locations of dead objects as free, leaving the heap fragmented. Compaction moves live objects next to each other to create a single contiguous block of free memory.

How does reference counting differ from tracing garbage collection?

Reference counting reclaims objects as soon as their reference count drops to zero, but fails to handle cyclic references. Tracing starts from roots and naturally handles cyclic references because unreachable cycles are never traversed.