Управление памятью в Java
Что такое стековая память?
Стек в Java — это раздел памяти, который содержит методы, локальные переменные и ссылочные переменные. К памяти стека всегда обращаются в порядке «последним пришел — первым обслужен». Локальные переменные создаются в стеке.
Что такое динамическая память?
Куча — это раздел памяти, который содержит объекты и может также содержать ссылочные переменные. Переменные экземпляра создаются в куче.
Распределение памяти в Java
Распределение памяти в Java — это процесс, при котором в программе выделяются разделы виртуальной памяти для хранения переменных и экземпляров структур и классов. Однако при объявлении объекту не выделяется память, а создается только ссылка. Для выделения памяти объекта используется метод new(), поэтому объекту всегда выделяется память в куче.
Территория Java Распределение памяти разделено на следующие разделы:
- куча
- Стек
- Code
- статический
Такое разделение памяти необходимо для эффективного управления ею.
- Территория код раздел содержит ваши байткодом.
- Территория Стек раздел памяти содержит методы, локальные переменные и ссылочные переменные.
- Территория куча раздел содержит Объекты (также может содержать ссылочные переменные).
- Территория статический раздел содержит Статические данные/методы.
Разница между локальной переменной и переменной экземпляра
Переменная экземпляра объявлен внутри класса, но не внутри метода
class Student{ int num; // num is instance variable public void showData{}
Локальная переменная объявлены внутри a метод, включающий метод Аргументы.
public void sum(int a){ int x = int a + 3; // a , x are local variables; }
Разница между стеком и кучей
Нажмите здесь если видео недоступно
Давайте рассмотрим пример, чтобы лучше понять это. Предположим, что ваш основной метод вызывает метод m1
public void m1{ int x=20 }
В стеке Java кадр будет создан методом m1.
Переменная X в m1 также будет создана в кадре для m1 в стеке. (См. изображение ниже).
Метод m1 вызывает метод m2. В стеке Java создается новый кадр для m2 поверх кадра m1.
Переменные b и c также будут созданы в кадре m2 в стеке.
public void m2(int b){ boolean c; }
Тот же метод m2 вызывает метод m3. Снова создается кадр m3 на вершине стека (см. изображение ниже).
Теперь предположим, что наш метод m3 создает объект для класса «Account», который имеет два переменная экземпляров int p и int q.
Account { Int p; Int q; }
Вот код метода m3
public void m3(){ Account ref = new Account(); // more code }
Оператор new Account() создаст объект аккаунта в куче.
Ссылочная переменная «ref» будет создана в стеке java.
Оператор присваивания «=» создаст ссылочную переменную, указывающую на объект в куче.
После того, как метод завершит свое выполнение, поток управления вернется к вызывающему методу. В данном случае это метод m2.
Стек метода m3 будет очищен.
Поскольку ссылочная переменная больше не будет указывать на объект в куче, ее можно будет использовать для сборки мусора.
После того, как метод m2 завершит свое выполнение, он будет вытащен из стека, а все его переменные будут очищены и больше не будут доступны для использования.
Аналогично для метода m1.
В конце концов поток управления вернется к начальной точке программы. Обычно это «основной» метод.
Что, если Object имеет ссылку в качестве переменной экземпляра?
public static void main(String args[]) { A parent = new A(); //more code } class A{ B child = new B(); int e; //more code } class B{ int c; int d; //more code }
В этом случае ссылочная переменная «child» будет создана в куче, которая, в свою очередь, будет указывать на свой объект, как показано на диаграмме ниже.
Что такое сбор мусора Java?
Сбор мусора в Java — это процесс, посредством которого программы автоматически выполняют управление памятью. Сборщик мусора (GC) находит неиспользуемые объекты и удаляет их, чтобы освободить память. В Javaдинамическое выделение памяти объектам достигается с помощью оператора new, который использует часть памяти, и память остается выделенной до тех пор, пока не появятся ссылки на использование объекта.
Когда на объект нет ссылок, предполагается, что он больше не нужен, и память, занятая объектом, может быть освобождена. Нет явной необходимости уничтожать объект, поскольку Java автоматически обрабатывает выделение.
Техника, позволяющая добиться этого, известна как Вывоз мусора. Программы, которые не освобождают память, могут в конечном итоге выйти из строя, если в системе не останется памяти для выделения. Говорят, что эти программы имеют утечки памяти. Сбор мусора в Java происходит автоматически во время жизни программы, что устраняет необходимость освобождать память и тем самым позволяет избежать утечек памяти.
В языке C ответственность за освобождение памяти, выделенной динамически, с помощью функции free() лежит на программисте. Вот где Java ведет управление памятью.
Примечание: Все объекты создаются в разделе Heap памяти. Подробнее об этом в следующем уроке.
Пример: изучить механизм сборщика мусора в 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 становится нулевым, но s3 по-прежнему указывает на объект и не подлежит сборке мусора Java.
Шаг 7) Раскомментируйте строки № 25 и 26. Сохраните, скомпилируйте и запустите код.
Шаг 8) На этом этапе нет ссылок, указывающих на объект, и он становится пригодным для сборки мусора. Оно будет удалено из памяти, и вернуть его обратно невозможно.
Как удалить объект в Java?
1) Если вы хотите, чтобы ваш объект имел право на сбор мусора, присвойте его ссылочной переменной значение null.
2) Примитивные типы не являются объектами. Им не может быть присвоено значение null.
Резюме:
- При вызове метода на вершине стека создается кадр.
- После завершения выполнения метода поток управления возвращается к вызывающему методу, и соответствующий ему кадр стека очищается.
- Локальные переменные создаются в стеке
- Переменные экземпляра создаются в куче и являются частью объекта, которому они принадлежат.
- Справочные переменные создаются в стеке.