Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Industrial programming >> java

Stack vs Heap в Java: Практическое руководство по распределению памяти

Что такое память стека (Stack)?

В Java стек — это непрерывная область памяти, которая хранит кадры вызовов методов, локальные переменные и ссылочные переменные. Каждый раз при вызове метода на стек помещается новый кадр. Память стека организована по принципу Last-In, First-Out (LIFO), что означает: самый последний вызов удаляется первым при возврате из метода.

Что такое память кучи (Heap)?

Куча — это область, где создаются объекты Java. Она содержит все экземпляры классов и, опционально, ссылочные переменные, указывающие на эти объекты. В отличие от стека, куча не привязана к времени жизни одного вызова метода, позволяя объектам существовать за пределами области видимости, в которой они были созданы.

Распределение памяти в Java

Распределение памяти в Java — это процесс резервирования виртуальной памяти для данных программы. Переменные не выделяются при объявлении; вместо этого создается ссылка. Когда используется оператор new, JVM выделяет место в куче для объекта.

Java делит память на четыре отдельные секции для эффективного управления:

  1. Heap (Куча)
  2. Stack (Стек)
  3. Code (Байт-код)
  4. Static (Данные класса)

Локальные переменные vs Переменные экземпляра

Переменные экземпляра объявляются внутри класса, но вне любого метода:

class Student {
    int num; // переменная экземпляра
    public void showData() {}
}

Локальные переменные объявляются внутри метода (или как параметры метода):

public void sum(int a) {
    int x = a + 3; // a и x — локальные переменные
}

Stack vs Heap в действии

Рассмотрим пример, иллюстрирующий взаимодействие стека и кучи при вызовах методов.

Предположим, метод main вызывает m1():

public void m1() {
    int x = 20;
}

Кадр для m1 помещается на стек. Локальная переменная x сохраняется в этом кадре.

Stack vs Heap в Java: Практическое руководство по распределению памяти

Когда m1 вызывает m2(int b), новый кадр добавляется поверх кадра m1:

public void m2(int b) {
    boolean c;
}
Stack vs Heap в Java: Практическое руководство по распределению памяти

Аналогично, m2 вызывает m3(), создавая еще один кадр:

Stack vs Heap в Java: Практическое руководство по распределению памяти

Внутри m3 создается объект Account в куче, а его ссылка ref находится в стеке:

class Account {
    int p;
    int q;
}
public void m3() {
    Account ref = new Account(); // дополнительный код
}
Stack vs Heap в Java: Практическое руководство по распределению памяти

Ссылочная переменная ref создается в кадре стека m3 и указывает на объект Account, выделенный в куче.

Stack vs Heap в Java: Практическое руководство по распределению памяти

Когда m3 завершается, его кадр стека снимается, оставляя объект Account без ссылок. Он становится пригодным для сборки мусора.

Stack vs Heap в Java: Практическое руководство по распределению памяти

Тот же процесс повторяется для m2 и m1, в конечном итоге возвращая управление в main.

Ссылочные переменные как переменные экземпляра

Рассмотрим класс A, который хранит ссылку на экземпляр B:

public static void main(String[] args) {
    A parent = new A(); // дополнительный код
}
class A {
    B child = new B();
    int e;
}
class B {
    int c;
    int d;
}

Здесь ссылка child хранится в куче как часть объекта A, указывая на свой собственный экземпляр B.

Stack vs Heap в Java: Практическое руководство по распределению памяти

Основные выводы

java

  1. Переменные и литералы в Java: подробное руководство
  2. Классы и объекты в Java: практическое руководство
  3. Абстрактные классы и методы в Java: полное руководство
  4. Вложенные и внутренние классы в Java: типы, примеры и лучшие практики
  5. Java throw vs throws: мастерство обработки исключений с практическими примерами
  6. Типы аннотаций в Java: предопределенные, кастомные и мета-аннотации
  7. Освоение Java Autoboxing и Unboxing: практические примеры и лучшие практики
  8. Замена строк в Java: replace(), replaceAll() и replaceFirst() подробно
  9. Переопределение методов в Java: настройка поведения суперкласса
  10. Java 10: размещение кучи на NV-DIMM через -XX:AllocateHeapAt