Ответ
В стеке хранятся примитивные типы данных (int, boolean, char и т.д.) и ссылки на объекты. Также в стеке хранятся фреймы методов — локальные переменные и информация о вызовах методов. Каждый поток имеет свой стек.
Пример:
void foo() {
int x = 5; // хранится в стеке
String s = "Hello"; // ссылка на объект в стеке, сам объект — в куче
}
Стек работает по принципу LIFO (Last In, First Out). При вызове метода создается новый фрейм, при завершении — удаляется. Размер стека ограничен, переполнение вызывает StackOverflowError.