Рубрики
Без рубрики

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

Пространство кучи Java против стека, распределение памяти в java. Куча против стека, Модель памяти на java, Управление памятью, стек против кучи, память на java

Автор оригинала: Pankaj Kumar.

Некоторое время назад я написал пару постов о Сборке мусора Java и Java передается по значению . После этого я получил много писем с объяснениями о Пространстве кучи Java , Памяти стека Java , Распределении памяти в Java и в чем различия между ними.

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

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

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

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

Память стека Java

Память стека Java используется для выполнения потока. Они содержат кратковременные значения для конкретного метода и ссылки на другие объекты в куче, на которые ссылается метод.

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

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

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

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

package com.journaldev.test;

public class Memory {

	public static void main(String[] args) { // Line 1
		int i=1; // Line 2
		Object obj = new Object(); // Line 3
		Memory mem = new Memory(); // Line 4
		mem.foo(obj); // Line 5
	} // Line 9

	private void foo(Object param) { // Line 6
		String str = param.toString(); //// Line 7
		System.out.println(str);
	} // Line 8

}

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

Давайте пройдемся по этапам выполнения программы.

  • Как только мы запускаем программу, она загружает все классы среды выполнения в пространство кучи. Когда метод main() найден в строке 1, среда выполнения Java создает память стека, которая будет использоваться потоком метода main ().
  • Мы создаем примитивную локальную переменную в строке 2, поэтому она создается и хранится в памяти стека метода main ().
  • Поскольку мы создаем объект в 3-й строке, он создается в памяти кучи, а память стека содержит ссылку на него. Аналогичный процесс происходит, когда мы создаем объект памяти в 4-й строке.
  • Теперь, когда мы вызываем метод foo() в 5-й строке, создается блок в верхней части стека, который будет использоваться методом foo (). Поскольку Java передается по значению, в блоке стека foo() в 6-й строке создается новая ссылка на объект.
  • Строка создается в 7-й строке, она помещается в пул Строк в пространстве кучи, и для нее создается ссылка в пространстве стека foo ().
  • метод foo() завершается в 8-й строке, в это время блок памяти, выделенный для foo() в стеке, становится свободным.
  • В строке 9 метод main() завершается, и память стека, созданная для метода main (), уничтожается. Кроме того, программа заканчивается на этой строке, следовательно, среда выполнения Java освобождает всю память и завершает выполнение программы.

Разница между пространством кучи Java и стековой памятью

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

  1. Память кучи используется всеми частями приложения, в то время как память стека используется только одним потоком выполнения.
  2. Всякий раз, когда создается объект, он всегда хранится в пространстве кучи, а память стека содержит ссылку на него. Память стека содержит только локальные примитивные переменные и ссылочные переменные на объекты в пространстве кучи.
  3. Объекты, хранящиеся в куче, доступны глобально, в то время как память стека недоступна другим потокам.
  4. Управление памятью в стеке выполняется способом LIFO, в то время как в кучной памяти оно более сложное, поскольку используется глобально. Кучная память делится на молодое поколение, Старое поколение и т.д., Подробнее см. в Сборка мусора Java .
  5. Память стека недолговечна, в то время как память кучи живет от начала до конца выполнения приложения.
  6. Мы можем использовать опцию -Xms и -Xmx JVM для определения размера запуска и максимального размера кучи памяти. Мы можем использовать -Xss для определения размера стековой памяти.
  7. Когда память стека заполнена, среда выполнения Java выдает java.lang.Ошибка StackOverflowError в то время как если память кучи заполнена, она выдает java.lang.OutOfMemoryError: Пространство кучи Java ошибка.
  8. Размер стековой памяти очень меньше по сравнению с памятью кучи. Из-за простоты распределения памяти (LIFO) стековая память работает очень быстро по сравнению с памятью кучи.

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

Список литературы: https://en.wikipedia.org/wiki/Java_memory_model https://blogs.oracle.com/jonthecollector/presenting-the-permanent-generation