Память кучи - мусор, собранный на Java.
Собирается ли сборщик стека?
Как восстанавливается память стека?
Память кучи - мусор, собранный на Java.
Собирается ли сборщик стека?
Как восстанавливается память стека?
Память в стеке содержит параметры метода и локальные переменные (точнее: ссылки на объекты и сами переменные для примитивных типов). Это будет автоматически удалено, если вы оставите этот метод. Если переменные являются ссылками (объектами), сами объекты находятся в куче и обрабатываются сборщиком мусора.
Таким образом, стек не является мусором, собранным так же, как куча, но стек - это форма автоматического управления памятью в нем (что предшествует сборке мусора).
A более подробный ответ дается Томасом Порнином, посмотрите на это более подробно.
Стек не является мусором, собранным в Java.
Стек, выделенная для данного вызова метода, освобождается при возврате метода. Поскольку это очень простая структура LIFO, нет необходимости в сборке мусора.
Одно место, где взаимодействуют стек и мусор, заключается в том, что ссылки в стеке являются корнями GC (что означает, что они являются корневыми ссылками, из которых решаются достижимость).
Стек может быть собрано в мусор. Однако в большинстве реализаций JVM он обрабатывается как, например, "стек", который по определению исключает сбор мусора.
То, что мы называем стеком, - это накопление контекстов активации метода: для каждого вызванного метода это концептуальная структура, которая содержит аргументы метода, локальные переменные, скрытый указатель на контекст для вызывающего метода и слот для сохраните указатель инструкции. Контекст активации недоступен как таковой из самого языка Java. Контекст становится бесполезным, когда метод выходит (с помощью return
или из-за созданного исключения). Так получилось, что, когда метод A называет метод B, гарантируется, что когда A восстанавливает контроль, контекст B становится бесполезным. Это означает, что время жизни контекста для B является поддиапазоном времени жизни контекста для A. Поэтому контексты активации (для данного потока) могут быть выделены с помощью дисциплины LIFO ( "Last In, First Out" ). В более простых словах стек: новый контекст активации помещается поверх стека контекстов, а первый контекст будет удален.
На практике контексты активации (также называемые стековыми кадрами) конкатенируются в порядке стека в выделенной области. Эта область получается из операционной системы при запуске потока, и операционная система возвращает ее, когда поток завершается. Верх стека обозначается конкретным указателем, который часто содержится в регистре CPU (это зависит от того, интерпретирует ли JVM или компилирует код). "Указатель на контекст вызывающего" является виртуальным; контекст вызывающего абонента обязательно расположен чуть ниже в порядке стека. GC не вмешивается: область для стека создается и регенерируется синхронно, из самой активности потока. Это также работает на многих языках, таких как C, которые вообще не имеют GC.
Теперь ничто не препятствует реализации JVM в противном случае, например. выделяя контексты активации в куче и собирая их GC. Обычно это не делается в виртуальных машинах Java, поскольку распределение стека выполняется быстрее. Но некоторые другие языки должны делать такие вещи, особенно те, которые играют с продолжениями, все еще используя GC (например, Scheme и его call-with-current-continuation
), потому что такие игры нарушают правило LIFO выше.
Пакетная часть памяти работает так же, как "стек". Я знаю, что это звучит плохо, но это точно, как это работает. Данные добавляются сверху, друг на друга (pushed onto the stack
) и автоматически удаляются из верхней части (popped off the stack
) по мере запуска вашей программы. Это не сбор мусора - и это не обязательно, поскольку эта память автоматически восстанавливается после того, как данные удаляются из стека. И когда я говорю об исправлении, я не имею в виду, что он де-распределяется - это просто то, что местоположение в памяти стека, где будут храниться следующие данные, уменьшается, поскольку данные удаляются.
Конечно, не сказать, что вам не нужно вообще беспокоиться о стеке. Если вы запустите рекурсивную функцию много раз, она в конечном итоге будет использовать все пространство стека. То же самое, если вы вызываете много функций, особенно если у них много параметров и/или локальных переменных.
Но суть в том, что память стека используется и исправлена, поскольку функции вводят и оставляют область - автоматически. Таким образом, в конце выполнения вашей программы вся память стека будет бесплатной, а затем выпущена обратно в операционную систему.
Если вы ссылаетесь на память, используемую в стеке, это не сбор мусора.
Java-виртуальная машина использует явные инструкции по байт-коду для резервирования и освобождения памяти в стеке, эти инструкции генерируются компилятором и управляют временем жизни примитивов, таких как int, boolean, double и object-references в стеке.
Планируется реализовать так называемую оптимизацию хвостовых вызовов, которая удалит некоторые записи из стека, как только станет известно, что они больше не используются, но я не знаю ни одного jvm, который уже поддерживает это.
Поэтому нет никакой сборки мусора для самого стека, только компилятор генерирует команды push и pop для управления использованием памяти.
Сама стек является частью потока. Стек выделяется при создании объекта потока и сборе мусора после прекращения потока, и объект потока больше не ссылается.
Все объекты в Java выделяются в куче. (По крайней мере, насколько спецификация идет, фактическая реализация может выделять их в стеке, если они прозрачно ведут себя так, как если бы они находились в куче.)
То, что коллекционируется, немного тонко. Если единственная ссылка на объект находится в одном стеке стека, и можно показать, что ссылка не будет использоваться снова, тогда объект может быть собран. Если объект используется только для чтения поля, то это поле может быть оптимизировано вперед, а объект собран ранее, чем вы могли ожидать.
Это обычно не имеет значения, если вы не используете финалисты (или предположительно Reference
s). В этом случае вы должны быть осторожны и использовать блокировки /volatile для обеспечения отношения happens-before
.
Когда потоки останавливаются, тогда обычно весь стек будет освобожден.
Все, что находится в стеке, рассматривается как глобальные корни сборщиком мусора. Итак, да, вы определенно можете сказать, что стек "сбор мусора".
Никто, данные не выталкиваются и не выгружаются из стека, поскольку у вас есть внутренние переменные в методах, во время вызовов методов и т.д. Вам не нужно заботиться об этом.
Нет. Стек не является мусором, собранным на Java. Каждый поток имеет свой собственный стек и содержит:
Эти значения переносятся в стек кадров в стек для каждого вызова метода. Поскольку стек следует за порядком "Last-in First-Out", в конце каждого вызова метода каждый стек стека, содержащий все данные, специфичные для метода, и ссылки на объекты, если они есть, выгружаются.
Следовательно, данные в стеке автоматически очищаются после того, как метод/программа выходит за рамки.