java стек и куча

Для оптимальной работы приложения JVM делит память на область стека (stack) и область кучи (heap). Всякий раз, когда мы объявляем новые переменные, создаем объекты или вызываем новый метод, JVM выделяет память для этих операций в стеке или в куче

В этой статье мы рассмотрим эти две области памяти: обозначим ключевые отличия между ними, рассмотрим, как они используют память, изучим предлагаемые ими функции и как их использовать

Стек работает по схеме LIFO (последним вошел, первым вышел). Всякий раз, когда вызывается новый метод, содержащий примитивные значения или ссылки на объекты, то на вершине стека под них выделяется блок памяти

Когда метод завершает выполнение, блок памяти, отведенный для его нужд, очищается, и пространство становится доступным для следующего метода

Эта область памяти используется для объектов и классов. Новые объекты всегда создаются в куче, а ссылки на них хранятся в стеке

Эти объекты имеют глобальный доступ и могут быть получены из любого места программы

Рассмотрим выполнение кода по шагам:

  1. До начала выполнения метода main(), в стеке будет выделено пространство для хранения примитивов и ссылок этого метода:
    • примитивное значение >intбудет храниться непосредственно в стеке
    • ссылочная переменная pName типа String будет создана в стеке, но сама строка будет храниться в области, называемой String Pool (является частью Кучи)
    • ссылочная переменная pтипа Personбудет также создана в памяти стека, но будет указывать на объект, расположенный в куче
  • Для вызова конструктора с параметрами Person(int, String) из метода main() в стеке, поверх предыдущего вызова метода main(), будет выделен блок памяти, который будет хранить:
    • this— ссылка на текущий объект
    • примитивное значение id
    • ссылочную переменную personNameтипа String, которая указывает на объект строки из пула строк

    Конструктор по умолчанию дополнительно вызывает метод setPersonName(), для которого будет выделен блок памяти в стеке поверх предыдущего вызова. Этот блок снова сохранит переменные способом, описанным выше

  • Для вновь созданного объекта p типа Person все переменные будут сохранены в памяти кучи
  • В Java есть такие понятия как Heap и Stack память. Сегодня мы узнаем разницу между ними и зачем они нужны. Как всегда, сначала в теории и затем на практике разберем эту сложную тему.

    Java Heap память

    Java Heap (куча) используется Java Runtime для выделения памяти под объекты и JRE классы. Создание нового объекта также происходит в куче. Здесь работает сборщик мусора: освобождает память путем удаления объектов, на которые нет каких-либо ссылок. Любой объект, созданный в куче, имеет глобальный доступ и на него могут ссылаться с любой части приложения.

    Stack память в Java

    Стековая память в Java работает по схеме LIFO (Последний-зашел-Первый-вышел). Всякий раз, когда вызывается метод, в памяти стека создается новый блок, который содержит примитивы и ссылки на другие объекты в методе. Как только метод заканчивает работу, блок также перестает использоваться, тем самым предоставляя доступ для следующего метода.
    Размер стековой памяти намного меньше объема памяти в куче.

    Давайте рассмотрим отличия стековой памяти и кучи на примере простой программы.

    На картинке ниже представлена память стека и кучи для программы выше

    А теперь рассмотри шаги выполнения нашей программы:

    1. Как только мы запустим программу, загружаются все классы среды выполнения в кучу. Потом метод main() находит строку 1 и Java Runtime создает стековую память для использования методом main().
    2. Далее в строке 2 создается int’овая переменная, которая хранится в памяти стека метода main() .
    3. Потом мы создали объект в строке 3 и он тут же появляется в куче, а стековая память содержит ссылку на него. Точно такой же процесс происходит, когда мы создаем объект Memory в строке 4 .
    4. Теперь в строке 5 мы вызываем метод exMethod() и тут же сразу создается блок на вершине стека, который будет использоваться этим методом. Поскольку в Java объекты и примитивы передаются по значению, то в строке 6 будет создана новая ссылка на объект, созданный в строке 3.
    5. Строка, созданная в строке 7 , отправляется в Пул строк (String Pool), который находится в куче. На эту строку также создается ссылка в стековой памяти метода exMethod() .
    6. Метод exMethod() завершается на строке 8 , поэтому блок стековой памяти для этого метода становится свободным.
    7. В строке 9 метод main() завершается, поэтому стековая память для метода main() будет уничтожена. Также программа заканчивается в этой строке, следовательно, Java Runtime освобождает всю память и завершает программу.

    Разница между Stack и Heap памятью в Java

    На основании приведенных выше объяснений, мы можем легко подытожить следующие различия между Heap и Stack памятью в Java.

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

    Вот и все, что нужно знать о Stack и Heap памяти в Java. Следите за обновлениями в разделе Полезности.

    Наверное, все, работающие с Java, знают об управлении памяти на уровне, что для ее распределения используется сборщик мусора. Не все, к сожалению, знают, как именно этот сборщик (-и) работает, и как именно организована память внутри процесса Java.

    Из-за этого иногда делается неверный вывод, что memory leaks в Java не бывает, и слишком задумываться о памяти не надо. Так же часто идут холивары по поводу чрезмерного расхода памяти.
    Все описанное далее относится к Sun-овской реализации JVM (HotSpot), версий 5.0+, конкретные детали и алгоритмы могут различаться для разных версий.

    Итак, память процесса различается на heap (куча) и non-heap (стек) память, и состоит из 5 областей (memory pools, memory spaces):
    • Eden Space (heap) – в этой области выделятся память под все создаваемые из программы объекты. Большая часть объектов живет недолго (итераторы, временные объекты, используемые внутри методов и т.п.), и удаляются при выполнении сборок мусора это области памяти, не перемещаются в другие области памяти. Когда данная область заполняется (т.е. количество выделенной памяти в этой области превышает некоторый заданный процент), GC выполняет быструю (minor collection) сборку мусора. По сравнению с полной сборкой мусора она занимает мало времени, и затрагивает только эту область памяти — очищает от устаревших объектов Eden Space и перемещает выжившие объекты в следующую область.
    • Survivor Space (heap) – сюда перемещаются объекты из предыдущей, после того, как они пережили хотя бы одну сборку мусора. Время от времени долгоживущие объекты из этой области перемещаются в Tenured Space.
    • Tenured (Old) Generation (heap) — Здесь скапливаются долгоживущие объекты (крупные высокоуровневые объекты, синглтоны, менеджеры ресурсов и проч.). Когда заполняется эта область, выполняется полная сборка мусора (full, major collection), которая обрабатывает все созданные JVM объекты.
    • Permanent Generation (non-heap) – Здесь хранится метаинформация, используемая JVM (используемые классы, методы и т.п.). В частноси
    • Code Cache (non-heap) — эта область используется JVM, когда включена JIT-компиляция, в ней кешируется скомпилированный платформенно — зависимый код.

    Вот тут — blogs.sun.com/vmrobot/entry/основы_сборки_мусора_в_hotspot есть хорошее описание работы сборщиков мусора, перепечатывать не вижу смысла, советую всем интересующимся ознакомиться подробней по ссылке.

    Статья не моя. но камрада Zorkus’a, который хотел бы получить инвайт :).

    Оцените статью