Start here. This is the direct spoken answer to practice first.
Overview
The useful distinction is which runtime resource is exhausted or retaining data, not a decorative stack-versus-heap diagram.
The Java heap holds ordinary objects and is managed by the garbage collector. Each thread has a stack containing method frames and local execution state, while class metadata is stored in Metaspace. The JVM also uses native memory for areas such as thread stacks, direct buffers, native libraries, and internal runtime structures. These areas have different limits and produce different symptoms, so an OutOfMemoryError is not automatically a heap leak.