Куча. Здесь живут все объекты, созданные через new, и массивы. Общая для всех потоков. Делится на поколения (молодое: Eden и Survivor; старое) или на регионы (G1, ZGC). Именно её обходит сборщик мусора.
Стек потока. Каждый вызов метода кладёт кадр: локальные переменные (примитивы — значением, объекты — ссылкой), аргументы, промежуточные значения. Метод вернулся — кадр снят, сборка мусора не нужна. Глубокая рекурсия переполняет стек — StackOverflowError.
Metaspace (Java 8+) — описания классов: поля, методы, байт-код, константный пул. Лежит в нативной памяти и по умолчанию растёт без ограничения. Утечка загрузчиков классов (передеплой в сервере приложений, динамически генерируемые классы) приводит к OutOfMemoryError: Metaspace. До Java 8 это была PermGen внутри кучи фиксированного размера.
Прочее вне кучи: кодовый кэш (скомпилированный JIT машинный код), direct ByteBuffer, структуры сборщика, стеки всех потоков. Поэтому процесс Java всегда занимает больше, чем -Xmx — важно в контейнерах.
Статические поля хранятся в объекте Class, то есть в куче, — частая путаница.