Stack и Heap в Java
И также присутствуют ссылки на объекты другие ( в данном случае на объект такого же класса ). Собственно вопрос. Где будут храниться локальные переменные и ссылки класса выделенного из main. В Heap или Stack ? Спасибо .
Отслеживать
34.4k 15 15 золотых знаков 65 65 серебряных знаков 94 94 бронзовых знака
задан 2 июн 2014 в 8:51
2,409 6 6 золотых знаков 30 30 серебряных знаков 42 42 бронзовых знака
@Alexandr Crospov эмм. а зачем такие тонкости знать простому девелоперу? Я бы понял, если бы вы писали компилятор или там что-то служебное для оси
2 июн 2014 в 10:32
@Barmaley, согласитесь, простому девелоперу полезно знать, откуда растут ноги у OutOfMemoryError, и почему часть из них просит Java heap, а другая — PermGen.
2 июн 2014 в 10:44
3 ответа 3
Сортировка: Сброс на вариант по умолчанию
Насколько я понимаю (знатоки Java пусть меня поправят), всё, что выделено при помощи new , лежит в heap-памяти. В частности, экземпляры классов тоже лежат в heap, вместе со всеми своими полями.
У класса самого по себе нету локальных переменных. Локальные переменные есть у его методов, эти переменные размещаются в стеке, когда метод вызывается.
Возможные отклонения от этой схемы (они реализованы в C#, не знаю, так ли в Java):
- Если оптимизатор может доказать, что экземпляр класса не покидает пределов метода, он может переместить его в стек невидимым для программиста образом для эффективности
- Не знаю, имеет ли право компилятор неявно перемещать в heap локальные переменные, захваченные лямбда-функцией.
Отслеживать
ответ дан 2 июн 2014 в 8:56
206k 28 28 золотых знаков 291 291 серебряный знак 526 526 бронзовых знаков
По второму пункту: создаёт копию значений захваченных локальных переменных.
3 июн 2014 в 5:47
@AlexeyM: Хм, значит, захватывать можно только final ?
3 июн 2014 в 7:18
В Java
3 июн 2014 в 15:52
@AlexeyM: Круто, не знал. Спасибо!
3 июн 2014 в 18:08
Ссылка на класс на стеке, сам экземпляр класса в heap’е. Кроме того, при включенном флаге -XX:+DoEscapeAnalysis и ключом -server JVM может размещать экземпляры классов на стеке, если на эти экземпляры нет ссылок за пределами блока (при этом оптимизируемый таким образом метод должен сначала откомпилироваться JIT). См. EscapeAnalysis.
Отслеживать
ответ дан 2 июн 2014 в 9:04
13.1k 1 1 золотой знак 28 28 серебряных знаков 28 28 бронзовых знаков
@a_gura: формально, ссылка может попасть в heap, если она — поле другого класса. Я бы делал разделение по критерию поле/локальная переменная.
2 июн 2014 в 9:07
@VladD если ссылка — это поле другого класса, она всегда в heap’е (в рамках самого класса), если только это не локальная копия ссылки или не сработал escape analysis для содержащего ее класса.
2 июн 2014 в 9:17
Стэк/Stack — находится в оперативной памяти (RAM) хранит ссылки на объекты, а также примитивы.
Куча/Heap (также в RAM) — хранит все объекты (не ссылки).
Permanent generation используется только JVM для хранения необходимых данных, в том числе метаданные о созданных объектах.
Постоянное хранилище (ROM) — хранит строковые литералы и константы.
Внешнее хранилище — хранит потоковые объекты (поток в виде байтов) и долгоживущие (persistent) объекты (сохраняют свое состояние после закрытия программы)
Отслеживать
ответ дан 5 дек 2016 в 10:45
Eugene Prokopenko Eugene Prokopenko
21 1 1 бронзовый знак
- java
- jvm
-
Важное на Мете
Связанные
Похожие
Подписаться на ленту
Лента вопроса
Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.
Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.10.27.43697
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
Основные принципы программирования: стек и куча
На данный момент этот блок не поддерживается, но мы не забыли о нём! Наша команда уже занята его разработкой, он будет доступен в ближайшее время.
Мы используем всё более продвинутые языки программирования, которые позволяют нам писать меньше кода и получать отличные результаты. За это приходится платить. Поскольку мы всё реже занимаемся низкоуровневыми вещами, нормальным становится то, что многие из нас не вполне понимают, что такое стек и куча, как на самом деле происходит компиляция, в чём разница между статической и динамической типизацией, и т.д. Я не говорю, что все программисты не знают об этих понятиях — я лишь считаю, что порой стоит возвращаться к таким олдскульным вещам.
Сегодня мы поговорим лишь об одной теме: стек и куча. И стек, и куча относятся к различным местоположениям, где происходит управление памятью, но стратегия этого управления кардинально отличается.
Стек
Стек — это область оперативной памяти, которая создаётся для каждого потока. Он работает в порядке LIFO (Last In, First Out), то есть последний добавленный в стек кусок памяти будет первым в очереди на вывод из стека. Каждый раз, когда функция объявляет новую переменную, она добавляется в стек, а когда эта переменная пропадает из области видимости (например, когда функция заканчивается), она автоматически удаляется из стека. Когда стековая переменная освобождается, эта область памяти становится доступной для других стековых переменных.
Из-за такой природы стека управление памятью оказывается весьма логичным и простым для выполнения на ЦП; это приводит к высокой скорости, в особенности потому, что время цикла обновления байта стека очень мало, т.е. этот байт скорее всего привязан к кэшу процессора. Тем не менее, у такой строгой формы управления есть и недостатки. Размер стека — это фиксированная величина, и превышение лимита выделенной на стеке памяти приведёт к переполнению стека. Размер задаётся при создании потока, и у каждой переменной есть максимальный размер, зависящий от типа данных. Это позволяет ограничивать размер некоторых переменных (например, целочисленных), и вынуждает заранее объявлять размер более сложных типов данных (например, массивов), поскольку стек не позволит им изменить его. Кроме того, переменные, расположенные на стеке, всегда являются локальными.
В итоге стек позволяет управлять памятью наиболее эффективным образом — но если вам нужно использовать динамические структуры данных или глобальные переменные, то стоит обратить внимание на кучу.
Куча
Куча — это хранилище памяти, также расположенное в ОЗУ, которое допускает динамическое выделение памяти и не работает по принципу стека: это просто склад для ваших переменных. Когда вы выделяете в куче участок памяти для хранения переменной, к ней можно обратиться не только в потоке, но и во всем приложении. Именно так определяются глобальные переменные. По завершении приложения все выделенные участки памяти освобождаются. Размер кучи задаётся при запуске приложения, но, в отличие от стека, он ограничен лишь физически, и это позволяет создавать динамические переменные.
Вы взаимодействуете с кучей посредством ссылок, обычно называемых указателями — это переменные, чьи значения являются адресами других переменных. Создавая указатель, вы указываете на местоположение памяти в куче, что задаёт начальное значение переменной и говорит программе, где получить доступ к этому значению. Из-за динамической природы кучи ЦП не принимает участия в контроле над ней; в языках без сборщика мусора (C, C++) разработчику нужно вручную освобождать участки памяти, которые больше не нужны. Если этого не делать, могут возникнуть утечки и фрагментация памяти, что существенно замедлит работу кучи.
Разработка на C++ с нуля в 2022 году: дорожная карта
В сравнении со стеком, куча работает медленнее, поскольку переменные разбросаны по памяти, а не сидят на верхушке стека. Некорректное управление памятью в куче приводит к замедлению её работы; тем не менее, это не уменьшает её важности — если вам нужно работать с динамическими или глобальными переменными, пользуйтесь кучей.
Заключение
Вот вы и познакомились с понятиями стека и кучи. Вкратце, стек — это очень быстрое хранилище памяти, работающее по принципу LIFO и управляемое процессором. Но эти преимущества приводят к ограниченному размеру стека и специальному способу получения значений. Для того, чтобы избежать этих ограничений, можно пользоваться кучей — она позволяет создавать динамические и глобальные переменные — но управлять памятью должен либо сборщик мусора, либо сам программист, да и работает куча медленнее.

Следите за новыми постами по любимым темам
Подпишитесь на интересующие вас теги, чтобы следить за новыми постами и быть в курсе событий.
Что такое Heap и Stack память в Java?

В Java есть такие понятия как Heap и Stack память. Сегодня мы узнаем разницу между ними и зачем они нужны. Как всегда, сначала в теории и затем на практике разберем эту сложную тему.
Java Heap память
Java Heap (куча) используется Java Runtime для выделения памяти под объекты и JRE классы. Создание нового объекта также происходит в куче. Здесь работает сборщик мусора: освобождает память путем удаления объектов, на которые нет каких-либо ссылок. Любой объект, созданный в куче, имеет глобальный доступ и на него могут ссылаться с любой части приложения.
Stack память в Java
Стековая память в Java работает по схеме LIFO (Последний-зашел-Первый-вышел). Всякий раз, когда вызывается метод, в памяти стека создается новый блок, который содержит примитивы и ссылки на другие объекты в методе. Как только метод заканчивает работу, блок также перестает использоваться, тем самым предоставляя доступ для следующего метода.
Размер стековой памяти намного меньше объема памяти в куче.
Давайте рассмотрим отличия стековой памяти и кучи на примере простой программы.
package ua . com . prologistic ;
public class Memory <
public static void main ( String [ ] args ) < // строка 1
int i = 1 ; // строка 2
Object object = new Object ( ) ; // строка 3
Memory memory = new Memory ( ) ; // строка 4
memory . exMethod ( object ) ; // строка 5
private void exMethod ( Object param ) < // строка 6
String string = param . toString ( ) ; // строка 7
System . out . println ( string ) ;
На картинке ниже представлена память стека и кучи для программы выше

А теперь рассмотри шаги выполнения нашей программы:
- Как только мы запустим программу, загружаются все классы среды выполнения в кучу. Потом метод main() находит строку 1 и Java Runtime создает стековую память для использования методом main().
- Далее в строке 2 создается int’овая переменная, которая хранится в памяти стека метода main() .
- Потом мы создали объект в строке 3 и он тут же появляется в куче, а стековая память содержит ссылку на него. Точно такой же процесс происходит, когда мы создаем объект Memory в строке 4 .
- Теперь в строке 5 мы вызываем метод exMethod() и тут же сразу создается блок на вершине стека, который будет использоваться этим методом. Поскольку в Java объекты и примитивы передаются по значению, то в строке 6 будет создана новая ссылка на объект, созданный в строке 3.
- Строка, созданная в строке 7 , отправляется в Пул строк (String Pool), который находится в куче. На эту строку также создается ссылка в стековой памяти метода exMethod() .
- Метод exMethod() завершается на строке 8 , поэтому блок стековой памяти для этого метода становится свободным.
- В строке 9 метод main() завершается, поэтому стековая память для метода main() будет уничтожена. Также программа заканчивается в этой строке, следовательно, Java Runtime освобождает всю память и завершает программу.
Разница между Stack и Heap памятью в Java
На основании приведенных выше объяснений, мы можем легко подытожить следующие различия между Heap и Stack памятью в Java.
- Куча используется всеми частями приложения в то время как стек используется только одним потоком исполнения программы.
- Всякий раз, когда создается объект, он всегда хранится в куче, а в памяти стека содержится ссылка на него. Память стека содержит только локальные переменные примитивных типов и ссылки на объекты в куче.
- Объекты в куче доступны с любой точки программы, в то время как стековая память не может быть доступна для других потоков.
- Управление памятью в стеке осуществляется по схеме LIFO .
- Стековая память существует лишь какое-то время работы программы, а память в куче живет с самого начала до конца работы программы.
- Мы можем использовать -Xms и -Xmx опции JVM, чтобы определить начальный и максимальный размер памяти в куче. Для стека определить размер памяти можно с помощью опции -Xss .
- Если память стека полностью занята, то Java Runtime бросает java.lang.StackOverflowError , а если память кучи заполнена, то бросается исключение java.lang.OutOfMemoryError: Java Heap Space .
- Размер памяти стека намного меньше памяти в куче. Из-за простоты распределения памяти ( LIFO ), стековая память работает намного быстрее кучи.
Вот и все, что нужно знать о Stack и Heap памяти в Java. Следите за обновлениями в разделе Полезности.
Стек (Stack) & Куча (Heap)
В Swift стек и куча — это две разные области памяти, которые используются для разных целей.
Стек (Stack)
Стек — это область памяти, которая используется для хранения локальных переменных и аргументов функций. Когда вы вызываете функцию, все ее локальные переменные и аргументы помещаются в стек, а когда функция завершается, эти переменные и аргументы удаляются из стека. Стек работает по принципу LIFO (Last In First Out), что означает, что последний добавленный элемент будет первым удаленным.
В Swift стек управляется автоматически и невидим для программиста. Когда вы объявляете локальную переменную или вызываете функцию, Swift автоматически выделяет необходимое количество памяти в стеке. Например, следующий код создает две локальные переменные в стеке:
import Foundation func someFunction()
Переменная «a» и константа «b» будут храниться в стеке, пока функция someFunction() выполняется. При завершении функции, они будут автоматически удалены из стека.
Куча (Heap)
Куча — это область памяти, которая используется для хранения объектов, которые не могут быть помещены в стек. Например, если вы создаете объект класса, Swift выделяет память для этого объекта в куче.
Куча в Swift управляется с помощью ARC (Automatic Reference Counting), что означает, что память освобождается автоматически, когда объект больше не используется. Когда объект создается в куче, Swift выделяет память для этого объекта и возвращает указатель на эту память. Этот указатель можно использовать для доступа к объекту и его свойствам.
Вот пример создания объекта класса в куче:
import Foundation class MyClass < var property: Int = 0 >let myObject = MyClass() myObject.property = 10
В этом примере мы создали объект класса «MyClass» в куче с помощью оператора «new». Затем мы установили значение свойства «property» объекта «myObject».
Отличия стека и кучи
Главное отличие между стеком и кучей в Swift заключается в том, что стек используется для хранения локальных переменных и аргументов функций, которые будут удалены из памяти при завершении функции, а куча используется для хранения объектов, которые будут оставаться в памяти, пока на них есть хотя бы одна ссылка на них.
Еще одно отличие между стеком и кучей заключается в том, что стек управляется автоматически, в то время как куча требует явного освобождения памяти. Если вы не освободите память, занятую объектом в куче, это может привести к утечке памяти.
Кроме того, в стеке память выделяется автоматически, когда вы объявляете переменную или вызываете функцию, в то время как в куче память выделяется явно, когда вы создаете объект. В Swift у вас есть возможность управлять, когда память выделяется и освобождается в куче, используя специальные функции, такие как «alloc» и «dealloc».
Важно понимать, что использование стека и кучи в Swift зависит от вашего кода и его потребностей. Если вы работаете с локальными переменными и аргументами функций, используйте стек. Если вы создаете объекты, которые должны оставаться в памяти, используйте кучу. В любом случае, Swift обеспечивает автоматическое управление памятью для обоих случаев, что облегчает разработку и предотвращает утечки памяти.
Еще немного об отличиях и типах, которые хранятся в той или иной области памяти
В Swift значения переменных могут быть либо типа значений (value type), либо ссылочного типа (reference type).
Типы значений (value) в Swift включают примитивные типы данных, такие как Integer, Boolean и Double, а также структуры, перечисления и кортежи. Типы значений хранятся непосредственно в стеке, в памяти, выделенной для функции или блока кода, в котором они определены. Когда переменная типа значения копируется в другую переменную или передается в функцию, копируется само значение, а не ссылка на объект.
Ссылочные типы (reference) в Swift включают классы, замыкания и функции. Объекты ссылочных типов хранятся в куче, и переменные, которые указывают на эти объекты, хранят ссылки на них. Когда переменная ссылочного типа копируется в другую переменную или передается в функцию, копируется только ссылка на объект, а не сам объект.
Использование типов значений и ссылочных типов в Swift имеет свои преимущества и недостатки. Типы значений обычно быстрее и проще в использовании, потому что они хранятся в стеке и копируются по значению. Однако они могут быть неэффективными для больших объектов или объектов, которые должны часто копироваться.
Ссылочные типы обычно менее эффективны, потому что они хранятся в куче и копируются только ссылки на них. Однако они могут быть более гибкими, потому что несколько переменных могут ссылаться на один и тот же объект, и изменения, сделанные в одной переменной, будут отражены в других переменных.
Наконец, важно помнить, что в Swift большинство стандартных типов данных, таких как String, Array и Dictionary, являются value типами, хранящимися в стеке.
Еще больше информации в нашем телегам канале.