Используются ли примитивы Java в стеке или куче?
Я просто знаю, что не-примитивы (объекты) идут в кучу, а методы идут в стеке, но как насчет примитивных переменных?
- обновление
На основе ответов я могу сказать, что куча может иметь новый стек и кучу для данного объекта? Учитывая, что объект будет иметь примитивные и ссылочные переменные..?
Ответы
Ответ 1
Примитивы, определенные локально, будут в стеке. Однако, если примитив был определен как часть экземпляра объекта, этот примитив был бы в куче.
public class Test
{
private static class HeapClass
{
public int y; // When an instance of HeapClass is allocated, this will be on the heap.
}
public static void main(String[] args)
{
int x=1; // This is on the stack.
}
}
Что касается обновления:
Объекты не имеют собственного стека. В моем примере int y
фактически будет частью каждого экземпляра HeapClass
. Всякий раз, когда выделяется экземпляр HeapClass (например, new HeapClass()
), все переменные-члены HeapClass добавляются в кучу. Таким образом, поскольку экземпляры HeapClass
выделяются в куче, int y
будет находиться в куче как часть экземпляра HeapClass
.
Однако все примитивные переменные, объявленные в теле любого метода, будут в стеке.
Как вы можете видеть в приведенном выше примере, int x
находится в стеке, потому что он объявлен в теле метода - не как член класса.
Ответ 2
Все локальные переменные (включая аргументы метода) идут в стек; объекты и все их поля хранятся в куче. Переменные всегда являются примитивами или ссылками на объекты.
Java-реализации могут фактически хранить объекты в куче таким образом, чтобы они все еще соответствовали спецификации. Точно так же локальные переменные могут храниться в регистрах или становиться нечеткими с помощью оптимизации.
Ответ 3
примитивы можно найти в обоих местах.
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, вы не можете освободить кусок, пока все части моложе его не будут освобождены. Это удобно сочетается с тем, как используется стек вызовов. Вы можете поместить что-нибудь в стек, если это нормально, когда эта вещь возвращается, когда ваша функция возвращается. Это оптимизация, так как очень быстро выделять и освобождать из стека, поскольку она поддерживает только то, что используется таким образом. Можно было бы сохранить все локальные переменные для функции в куче в реализации, если захотите. Куча более гибкая и, следовательно, более дорогая в использовании. Неверно было бы сказать, что у объекта есть стек и куча, как я уже сказал, что отличает стек от кучи не то, что в нем, а доступные операции.
Ответ 4
Примитивные значения выделяются в стеке, если они не являются полями объекта, и в этом случае они идут в кучу. Стек используется для оценки и выполнения, поэтому нет смысла говорить, что объекты с примитивными полями имеют стек - он по-прежнему считается частью кучи. Даже объекты Stack
выделяются в куче.