Почему следующий массив помещается в кучу, а не в стек в Java

Недавно я узнал, что объекты могут быть помещены в стек или в кучу, а место их размещения определяется анализом побега. (Объявление нескольких массивов с 64 элементами в 1000 раз быстрее, чем объявление массива из 65 элементов)

В следующем примере я думаю, что объект «тест» помещается в кучу, что значительно увеличивает время выполнения:

public static void main(String args[]) {
    double start = System.nanoTime();
    long job = 100000000;// 100 million
    int total = 0;
    for (long i = 0; i < job; i++) {
        int j = 0;
        double[] test = new double[63];
        test[0] =1;
        total += test[0];
        while (true) {
            if (j == 0)
                break;
            j--;
        }
        test[0] = 10; // this makes a really big difference
    }
    double end = System.nanoTime();
    System.out.println("Total runtime = " + (end - start) / 1000000 + " ms" + " total ="+ total);
}

Если либо цикл while удален, либо "test[0] = 10;" , проверка объекта помещается в стек (я понял это из-за того, что сборщик мусора в этом случае не вызывается, тогда как он вызывается, когда присутствуют оба. Также время выполнения составляет 350 мс вместо 6803 мс).

Мой вопрос: почему тест объекта помещается в кучу, если я изменяю/получаю доступ к содержимому объекта после цикла while?


person Sipko    schedule 15.09.2013    source источник
comment
test — это Object.. Более того, когда вы видите ключевое слово new, это должно быть намеком на то, что задействована куча..   -  person Maroun    schedule 15.09.2013
comment
Прошу прощения, я перепутал термины Объект и переменная. Я отредактировал его.   -  person Sipko    schedule 15.09.2013
comment
@Maroun Maroun Из этого сообщения: noredirect=1#18810801" title="объявление нескольких массивов с 64 элементами на 1000 быстрее, чем объявление массива">stackoverflow.com/questions/18810505/ , я понимаю, что объекты могут быть помещены в стек, который не является частью куча, поправьте меня, если я неправильно понял пожалуйста.   -  person Sipko    schedule 15.09.2013
comment
Хотя объекты, которые не выходят за пределы метода, технически могут быть размещены в стеке, это не так. Взято из здесь: После анализа побега серверный компилятор удаляет скалярные заменяемые объекты и соответствующие блокировки из сгенерированного кода. Компилятор сервера также устраняет блокировки для всех неглобальных экранирующих объектов. Он не заменяет выделение кучи выделением стека для неглобально экранирующих объектов.   -  person kiheru    schedule 15.09.2013
comment
Пожалуйста, исправьте код. Что-то не так в первых строчках. Однако я не вижу разницы в производительности при тестировании исправленного кода на моей машине.   -  person nosid    schedule 15.09.2013
comment
@nosid Извините, я случайно дважды вставил и удалил только часть полной копии. Исправлено сейчас.   -  person Sipko    schedule 15.09.2013
comment
@nosid вы не видите никакой разницы в производительности, когда выходите из теста [0] = 10 или нет? Спасибо, что изучили и этот вопрос, кстати.   -  person Sipko    schedule 15.09.2013


Ответы (2)


test — это локальная ссылочная переменная для вашего основного метода. Все локальные переменные хранятся в стеке. Вот изображение, чтобы вы поняли, что находится в куче, а что в стеке:

введите здесь описание изображения

person Juned Ahsan    schedule 15.09.2013
comment
Но если бы тест был в стеке, сборщик мусора не вызывался бы, верно? Также это не объясняет, почему это занимает больше времени, если я изменяю один из элементов внутри объекта. - person Sipko; 15.09.2013

Также время выполнения составляет 350 мс вместо 6803 мс.

Я думаю, что дело не в стеке/куче, а в оптимизации. Я не уверен, как именно работает JIT-оптимизация Java, но аналогичный код на C/C++ после оптимизации будет выглядеть так:

public static void main(String args[]) {
    double start = System.nanoTime();
    long job = 100000000;// 100 million
    int total = 100000000;
    double end = System.nanoTime();
    System.out.println("Total runtime = " + (end - start) / 1000000 + " ms" + " total ="+ total);
}

возможно, если вы обратитесь к тесту:

test[0]=10; 

это приводит к тому, что цикл for не может быть «удален»

person alhugone    schedule 15.09.2013