Примитивы Java идут в стеке или куче? - PullRequest
55 голосов
/ 05 сентября 2010

Я просто знаю, что не примитивы (объекты) идут в кучу, а методы идут в стек, но как насчет примитивных переменных?1005 *

Исходя из ответов, я могу сказать, что куча может иметь новый стек и кучу для данного объекта?Учитывая, что объект будет иметь примитивные и ссылочные переменные ..?

Ответы [ 4 ]

85 голосов
/ 05 сентября 2010

Примитивы, определенные локально, будут в стеке. Однако, если примитив был определен как часть экземпляра объекта, этот примитив был бы в куче.

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 Test.HeapClass()), все переменные-члены HeapClass добавляются в кучу. Таким образом, поскольку экземпляры HeapClass выделяются в куче, int y будет в куче как часть экземпляра HeapClass.

Однако все примитивные переменные, объявленные в теле любого метода, будут в стеке .

Как видно из приведенного выше примера, int x находится в стеке, поскольку он объявлен в теле метода, а не в качестве члена класса.

19 голосов
/ 05 сентября 2010

Все локальные переменные (включая аргументы метода) помещаются в стек; объекты и все их поля хранятся в куче. Переменные всегда являются примитивами или ссылками на объекты.

Реализации Java могут фактически хранить объекты в куче таким образом, чтобы он все еще соответствовал спецификации. Точно так же локальные переменные могут храниться в регистрах или становиться нечеткими при оптимизации.

10 голосов
/ 05 сентября 2010

примитивов можно найти в обоих местах.

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, вы не можете освободить часть, пока все части моложе, чем она также не была освобождена.Это удобно согласуется с тем, как используется стек вызовов.Вы можете поместить что-нибудь в стек, если это нормально, когда эта функция исчезнет, ​​когда ваша функция вернется.Это оптимизация, поскольку она очень быстро выделяется и освобождается из стека, поскольку поддерживает только использование таким образом.При желании можно хранить все локальные переменные для функции в куче в реализации.Куча более гибкая и, следовательно, более дорогая в использовании.Было бы неправильно сказать, что у объекта есть стек и куча, как я уже сказал, что отличает стек от кучи не от того, что в нем, а от доступных операций.

7 голосов
/ 05 сентября 2010

Примитивные значения распределяются в стеке, если они не являются полями объекта, и в этом случае они помещаются в кучу.Стек используется для оценки и выполнения, поэтому нет смысла говорить, что объекты с примитивными полями имеют стек - он все еще считается частью кучи.Даже Stack объекты размещены в куче.

...