1. Start at the root set: local + global variables
  2. Mark all objects that are reachable from the root set
  3. Sweep all non-reachable objects and add to the free list

Requires slow allocation because the heap is never defragmented.