Управление памятью в Java

⚡ Умное резюме

Управление памятью в Java объясняется, как JVM распределяет память во время выполнения между стеком, кучей и т. д. Codeа также статические области, как происходит передача ссылок на объекты во время вызовов методов и как сборщик мусора освобождает недоступные объекты, чтобы приложения оставались стабильными и свободными от утечек памяти.

  • ???? Структура памяти JVM: Java Память разделена на кучу (Heap) для объектов, стек (Stack) для фреймов методов и локальных переменных, а также выделенные области для байт-кода и статических данных.
  • 📚 Стек против кучи: Стековые фреймы следуют принципу «последний вошел — первый вышел» и хранят примитивы и ссылки, в то время как куча содержит все объекты, созданные с помощью оператора new.
  • ♻️ Вывоз мусора: Сборщик мусора tracобеспечивает доступность через цепочки ссылок и автоматически освобождает память для объектов, к которым не может получить доступ ни один поток.
  • Современные коллекционеры: В производственных средах все чаще используются алгоритмы G1, ZGC и Shenandoah для сбора мусора с минимальными паузами в многогигабайтных кучах.
  • 🧪 Практический пример: В пошаговом руководстве по классу Student показано, когда ссылки становятся доступными для сбора мусора и как обнуление ссылок освобождает базовый объект.

Управление памятью в Java

Что такое стековая память в Java?

Стек памяти в Java Стек — это область памяти JVM, в которой хранятся кадры методов, локальные переменные и переменные-ссылки для каждого потока. Доступ к стеку всегда осуществляется в порядке «последний вошел — первый вышел», поэтому последний вызванный метод находится наверху, а его локальные переменные помещаются в стек и извлекаются из него вместе с кадром.

Каждая нить в Java Виртуальная машина получает собственный стек, который обеспечивает изоляцию вызовов методов и потокобезопасность по своей конструкции. Примитивные локальные переменные, такие как int, boolean и double, находятся непосредственно внутри стека, в то время как ссылки на объекты, хранящиеся в стеке, указывают на объекты, выделенные в куче.

Что такое куча памяти в Java?

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

Куча — это область, которой управляет сборщик мусора. В современных JVM HotSpot куча разделена на молодое поколение для объектов с коротким сроком жизни и старое поколение для объектов с длительным сроком жизни, при этом метаданные классов хранятся в отдельной собственной области, называемой метапространством.

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

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

Java Выделение памяти разделено на следующие разделы:

  1. куча
  2. Стек
  3. Code
  4. статический

Такое разделение памяти необходимо для эффективного управления средой выполнения.

  • Code В этом разделе содержится ваш скомпилированный байткодом.
  • Стек секционные магазины методы, локальные переменные и эталонные переменные.
  • куча раздел содержит объекты а также могут содержать ссылочные переменные, хранящиеся в качестве полей экземпляра.
  • статический раздел содержит статические данные и статические методы общий для всех экземпляров.

Разница между локальной переменной и переменной экземпляра

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

class Student{ 
int num; // num is instance variable 
public void showData{}

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

public void sum(int a){

int x = a + 3;

// a, x are local variables

}

Разница между стеком и кучей

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

Нажмите здесь если видео недоступно

Чтобы увидеть, как взаимодействуют стек и куча, рассмотрим основной метод, который вызывает метод m1.

public void m1{
int x = 20;
}

В стеке JVM для метода m1 создаётся кадр.

Java Стек и куча

Переменная x в m1 также создается в фрейме для m1 в стеке, как показано на изображении ниже.

Java Стек и куча

Затем метод m1 вызывает метод m2. В стеке создается новый кадр для метода m2 поверх кадра для метода m1.

Java Стек и куча

Java Стек и куча

Локальные переменные b и c также создаются внутри фрейма для m2 в стеке.

public void m2(int b){
boolean c;
}

Далее, m2 вызывает метод m3. И снова, на вершине стека создается фрейм для m3, как показано ниже.

Java Стек и куча

Java Стек и куча

Теперь предположим, что метод m3 создает объект для класса Account, который содержит два элемента. переменные экземпляра int p и int q.

class Account {
    int p;
    int q;
}

Вот код для метода m3.

public void m3(){
    Account ref = new Account();
    // more code
}

Оператор `new Account()` создает объект типа `Account` в куче.

Java Стек и куча

Переменная-ссылка ref создается в стеке внутри фрейма для m3.

Java Стек и куча

Оператор присваивания заставляет переменную-ссылку указывать на объект в куче.

Java Стек и куча

После завершения выполнения метода управление возвращается вызывающему методу, которым в данном случае является метод m2.

Java Стек и куча

Кадр для метода m3 выгружается из стека.

Java Стек и куча

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

Java Стек и куча

После завершения работы метода m2 он удаляется из стека, и все его переменные становятся недоступными. То же самое происходит с методом m1, и в конечном итоге управление возвращается к основному методу.

Что произойдет, если объект будет использовать другую ссылку в качестве своей переменной экземпляра?

public static void main(String args[]) {
    A parent = new A();
    // more code
}
class A {
    B child = new B();
    int e;
}
class B {
    int c;
    int d;
}

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

Java Стек и куча

Что такое сбор мусора Java?

Сбор мусора в Java Это процесс, посредством которого JVM автоматически управляет памятью. Сборщик мусора находит объекты, которые больше недоступны из каких-либо активных ссылок, и освобождает их память. Динамическое выделение памяти происходит с помощью оператора new, и память остается выделенной до тех пор, пока программа больше не будет содержать ссылок на этот объект.

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

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

В языке C, напротив, программист отвечает за освобождение памяти, динамически выделенной с помощью функции free(). Именно здесь и возникает проблема. Java Управление памятью дает существенное преимущество.

Современные JVM HotSpot поставляются с несколькими сборщиками мусора, настроенными для различных рабочих нагрузок. Сборщик мусора G1 по умолчанию ориентирован на сбалансированную пропускную способность и время пауз на многогигабайтных кучах. ZGC и Shenandoah нацелены на паузы менее миллисекунды на очень больших кучах, что делает их наиболее эффективными.tracЭто особенно важно для сервисов, чувствительных к задержкам. Выбор правильного сборщика и настройка размеров молодого поколения, старого поколения и метапространства — ключевой навык для этого. Java перформансная работа.

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

Пример: изучить механизм сборщика мусора в Java

В этом пошаговом руководстве показано, когда ссылки становятся доступными для сборки мусора внутри простой программы.

Шаг 1) Скопируйте следующий код в редактор.

class Student{
int a;
int b;
  public void setData(int c,int d){
    a=c;
    b=d;
  }
  public void showData(){
    System.out.println("Value of a = "+a);
    System.out.println("Value of b = "+b);
  }
  public static void main(String args[]){
    Student s1 = new Student();
    Student s2 = new Student();
    s1.setData(1,2);
    s2.setData(3,4);
    s1.showData();
    s2.showData();
    //Student s3;
    //s3=s2;
    //s3.showData();
    //s2=null;
    //s3.showData();
    //s3=null;
    //s3.showData();
  }
}

Шаг 2) Сохраните, скомпилируйте и запустите код. Как показано на диаграмме, создаются два объекта и две переменные-ссылки.

 Механизм сборщика мусора

Шаг 3) Раскомментируйте строки 20, 21 и 22. Сохраните, скомпилируйте и запустите код.

Шаг 4) Как показано на диаграмме ниже, теперь две переменные-ссылки указывают на один и тот же объект.

Механизм сборщика мусора

Шаг 5) Раскомментируйте строки 23 и 24. Сохраните, скомпилируйте и запустите код.

Шаг 6) Как показано ниже, s2 становится равным null, но s3 по-прежнему указывает на объект, поэтому объект еще не подлежит сборке мусора.

 Механизм сборщика мусора

Шаг 7) Раскомментируйте строки 25 и 26. Сохраните, скомпилируйте и запустите код.

Шаг 8) На данном этапе никакие ссылки не указывают на объект, поэтому он становится доступным для сборки мусора. Сборщик мусора удаляет его из памяти, и восстановить его невозможно.

 Изучите сборщик мусора

Как удалить объект в Java?

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

1) Чтобы объект стал доступен для сборки мусора, присвойте значение null каждой переменной-ссылке, указывающей на него.

2) Примитивные типы не являются объектами, поэтому им нельзя присвоить значение null. Их память автоматически освобождается при удалении фрейма из окружающего стека.

Как удалить объект в Java

Часто задаваемые вопросы (FAQ)

Стек хранит кадры методов, локальные переменные и ссылки в порядке «последний вошел — первый вышел» для каждого потока. Куча хранит все объекты, созданные с помощью оператора `new`, и является общей для всех потоков, поэтому ею управляет сборщик мусора.

Сборщик мусора проходит по цепочкам ссылок от корневых узлов сборщика мусора, таких как активные потоки и статические поля. Любой объект, недоступный из корневого узла, считается недоступным и становится доступным для освобождения во время следующего цикла сборки мусора.

В области «Молодое поколение» хранятся недолговечные объекты в пространствах «Эдем» и «Выживший». В области «Старое поколение» хранятся объекты, которые сохраняются после нескольких сборок. Метапространство — это область собственной памяти, которая хранит метаданные классов и заменила более старую область «Постоянное поколение». Java 8.

G1 — это значение по умолчанию, подходящее для большинства рабочих нагрузок на многогигабайтных кучах. ZGC и Shenandoah ориентированы на паузы менее миллисекунды на очень больших кучах и являются хорошим выбором для служб, чувствительных к задержкам, работающих на Java 17 или позже.

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

Да. Инструменты оптимизации на основе ИИ анализируют журналы сборки мусора, скорости выделения памяти и гистограммы пауз, чтобы рекомендовать размеры кучи, флаги сборщика мусора и коэффициенты молодого поколения. Они сокращают цикл обратной связи по сравнению с ручной настройкой, особенно для рабочих нагрузок G1, ZGC и Shenandoah.

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

Подведем итог этой публикации следующим образом: