Память стека и пространство кучи в Java

Память стека и пространство кучи в Java

1. Вступление

Для оптимального запуска приложения JVM делит память на стек и кучную память. Whenever we declare new variables and objects, call new method, declare a String or perform similar operations, JVM designates memory to these operations from either Stack Memory or Heap Space.с

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

2. Стековая память в Java

Stack Memory in Java is used for static memory allocation and the execution of a thread. Он содержит примитивные значения, специфичные для метода, и ссылки на объекты в куче, на которые ссылается метод.

Доступ к этой памяти осуществляется в порядке «последний пришел - первым вышел» (LIFO). Каждый раз, когда вызывается новый метод, создается новый блок в верхней части стека, который содержит значения, специфичные для этого метода, такие как примитивные переменные и ссылки на объекты.

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

2.1. Ключевые особенности стековой памяти

Помимо того, что мы уже обсуждали, ниже приведены некоторые другие особенности стековой памяти:

  • Он растет и уменьшается по мере того, как новые методы вызываются и возвращаются соответственно

  • Переменные внутри стека существуют только до тех пор, пока работает метод, который их создал

  • Он автоматически выделяется и освобождается, когда метод завершает выполнение.

  • Если эта память заполнена, Java выдаетjava.lang.StackOverFlowError

  • Доступ к этой памяти быстрый по сравнению с кучей памяти

  • Эта память является потокобезопасной, поскольку каждый поток работает в своем собственном стеке

3. Пространство кучи в Java

Heap space in Java is used for dynamic memory allocation for Java objects and JRE classes at the runtime. Новые объекты всегда создаются в пространстве кучи, а ссылки на эти объекты хранятся в памяти стека.

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

Эта модель памяти далее разбита на более мелкие части, называемые поколениями, это:

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

  2. Old or Tenured Generation – здесь хранятся давно уцелевшие объекты. Когда объекты хранятся в молодом поколении, устанавливается порог возраста объекта, и когда этот порог достигается, объект перемещается в старое поколение.

  3. Permanent Generation – - это метаданные JVM для классов времени выполнения и методов приложения.

Эти разные порции также обсуждаются в этой статье -Difference Between JVM, JRE, and JDK.

Мы всегда можем манипулировать размером кучи памяти согласно нашему требованию. Для получения дополнительной информации посетите этотlinked example article.

3.1. Ключевые особенности Java Heap Memory

Помимо того, что мы уже обсуждали, ниже приведены некоторые другие особенности пространства кучи:

  • Доступ к нему осуществляется с помощью сложных методов управления памятью, включая молодое поколение, старое или постоянное поколение и постоянное поколение.

  • Если пространство кучи заполнено, Java выдаетjava.lang.OutOfMemoryError

  • Доступ к этой памяти относительно медленнее, чем к памяти стека

  • Эта память, в отличие от стека, не освобождается автоматически. Требуется сборщик мусора, чтобы освободить неиспользуемые объекты, чтобы сохранить эффективность использования памяти

  • В отличие от стека, куча не является потокобезопасной и ее необходимо защищать путем правильной синхронизации кода.

4. пример

Основываясь на том, что мы узнали, давайте проанализируем простой код Java и оценим, как здесь управляется память:

class Person {
    int pid;
    String name;

    // constructor, setters/getters
}

public class Driver {
    public static void main(String[] args) {
        int id = 23;
        String pName = "Jon";
        Person p = null;
        p = new Person(id, pName);
    }
}

Давайте разберем это шаг за шагом:

  1. При входе в методmain() в стековой памяти будет создано пространство для хранения примитивов и ссылок этого метода.

    • Примитивное значение целого числаid будет храниться непосредственно в стековой памяти.

    • Ссылочная переменнаяoft typePerson will также будет создана в стековой памяти, которая будет указывать на фактический объект в куче.

  2. Вызов параметризованного конструктораPerson(int, String) изmain() выделит дополнительную память поверх предыдущего стека. Это будет хранить:

    • Ссылка на объектthis вызывающего объекта в стековой памяти

    • Примитивное значениеid попадает в стековую память

    • Ссылочная переменнаяString аргументаpersonName, которая будет указывать на фактическую строку из пула строк в памяти кучи

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

  4. Однако для вновь созданного объектаoft typePerson все переменные экземпляра будут храниться в динамической памяти.

Это распределение объясняется на этой диаграмме:

image

5. Резюме

Прежде чем мы завершим эту статью, давайте кратко подведем итоги различий между памятью стека и пространством кучи:

параметр Стек памяти Куча пространства

заявка

Стек используется по частям, по одной во время выполнения потока

Все приложение использует пространство кучи во время выполнения

Size

Стек имеет ограничения по размеру в зависимости от ОС и обычно меньше, чем куча.

Размер кучи не ограничен.

Место хранения

Хранит только примитивные переменные и ссылки на объекты, созданные в Heap Space.

Здесь хранятся все вновь созданные объекты.

порядок

Доступ к нему осуществляется с помощью системы распределения памяти Last-in First-Out (LIFO).

Доступ к этой памяти осуществляется с помощью сложных методов управления памятью, включая молодое поколение, старое или постоянное поколение и постоянное поколение.

Life

Память стека существует только до тех пор, пока выполняется текущий метод

Пространство в куче существует, пока приложение работает

КПД

Сравнительно намного быстрее выделять по сравнению с кучей

Медленнее выделяется по сравнению со стеком

Allocation/Deallocation

Эта память автоматически выделяется и освобождается при вызове и возврате метода соответственно.

Пространство кучи выделяется при создании новых объектов и освобождается с помощью Gargabe Collector, когда на них больше нет ссылок.

6. Заключение

Стек и куча - это два способа, которыми Java выделяет память. В этой статье мы поняли, как они работают и когда их использовать для разработки лучших программ на Java.

Чтобы узнать больше об управлении памятью в Java, посмотритеthis article here. Мы также обсудили сборщик мусора JVM, который кратко обсуждаетсяover in this article.