Glossary

Garbage Collection

Garbage collection (GC) is the automatic process of identifying and freeing memory occupied by objects that are no longer reachable from the program, preventing memory from being exhausted by unused allocations.

Explanation

Languages like C require manual memory management: you allocate memory with malloc and free it with free. Forgetting to free memory causes memory leaks; freeing memory too early causes use-after-free bugs. JavaScript, Python, and Java use garbage collection to automate this: the runtime periodically finds objects that are no longer reachable from any live reference and frees their memory. The dominant GC algorithm is mark-and-sweep: starting from "roots" (global variables, the call stack, and closures), the GC traverses all reachable objects, marking them. Anything not marked is unreachable — garbage — and its memory is reclaimed. Modern GCs use generational collection (most objects die young; collect the young generation frequently and cheaply), incremental/concurrent collection (GC work is interleaved with the program to reduce pause time), and compaction (move live objects together, eliminating fragmentation). Memory leaks in JavaScript: even though GC is automatic, you can still leak memory by accidentally keeping references to objects you no longer need. Common sources: event listeners never removed (the listener closure keeps the target object alive), global variables accumulating data (growing arrays/maps that are never cleared), closures capturing large objects in their scope, and uncleaned setInterval callbacks. WeakMap and WeakSet hold weak references — if the referenced object has no other references, it can be garbage collected even though it's in the WeakMap/WeakSet. This makes them ideal for caching computed values for objects without preventing GC of those objects.

Code Example

javascript
// Memory leaks and how to prevent them

// LEAK 1: Uncleaned event listeners
function attachHandler() {
  const data = new Array(10000).fill(0); // large allocation
  document.addEventListener('click', () => console.log(data.length));
  // Listener keeps 'data' alive forever — GC can't collect it
}

// FIX: Remove the listener when done
function attachHandlerFixed() {
  const data = new Array(10000).fill(0);
  const handler = () => console.log(data.length);
  document.addEventListener('click', handler);
  return () => document.removeEventListener('click', handler); // cleanup
}

// LEAK 2: Growing cache without eviction
const cache = {};  // never cleared — grows unbounded
function getValue(key) {
  if (!cache[key]) cache[key] = expensiveCompute(key);
  return cache[key];
}

// FIX: Use WeakMap (keys are weakly referenced) or bounded LRU cache
const weakCache = new WeakMap();
function getValueWeak(obj) {
  if (!weakCache.has(obj)) weakCache.set(obj, expensiveCompute(obj));
  return weakCache.get(obj);
}
// When 'obj' is no longer referenced elsewhere, weakCache entry is GC'd

// LEAK 3: setInterval without cleanup
const intervalId = setInterval(() => {
  processData(); // closure may capture large data
}, 1000);
// Always clear when component unmounts or interval is no longer needed:
clearInterval(intervalId);

Why It Matters for Engineers

Memory leaks cause applications to gradually consume more and more RAM until they crash or become unresponsive. In long-running Node.js servers and single-page applications, leaks that seem harmless in testing cause production crashes after hours or days of operation. Chrome DevTools Memory profiler and Node.js's heap snapshots are the tools for diagnosing them. Understanding GC also explains why JavaScript pauses occasionally (GC pause), why creating thousands of short-lived objects is fine (young generation collection is cheap), and why large, long-lived objects are more problematic for GC efficiency.

Related Terms

Closure · Variable · Event Loop

Learn This In Practice

Go deeper with the full module on Beyond Vibe Code.

Programming Foundations → →