примитивы можно найти в обоих местах.
class Foo
{
public int x;
public static void Main()
{
int y = 3; // y is on the stack
Foo f = new Foo(); // f.x is probably on the heap
}
}
кроме вас не должно волноваться, если вы не строите JVM. Действительно умный оптимизатор может решить, что, поскольку Foo, что f указывает на то, что никогда не ускользает от Main, и никогда не переходит к другой функции, можно безопасно выделить его в стеке.
Что касается обновления:
стека и кучи не отличаются тем, что хранится в них, а скорее операции, предусмотренные им. Стек позволяет вам выделить кусок памяти в режиме LIFO, вы не можете освободить кусок, пока все части моложе его не будут освобождены. Это удобно сочетается с тем, как используется стек вызовов. Вы можете поместить что-нибудь в стек, если это нормально, когда эта вещь возвращается, когда ваша функция возвращается. Это оптимизация, так как очень быстро выделять и освобождать из стека, поскольку она поддерживает только то, что используется таким образом. Можно было бы сохранить все локальные переменные для функции в куче в реализации, если захотите. Куча более гибкая и, следовательно, более дорогая в использовании. Неверно было бы сказать, что у объекта есть стек и куча, как я уже сказал, что отличает стек от кучи не то, что в нем, а доступные операции.
Каждый поток имеет свой собственный стек, а не каждый объект. Если есть только один поток, то есть только один стек. – Alex