Я знаю концепцию пула констант и пула констант String, используемых JVM для обработки литералов String. Но я не знаю, какой тип памяти используется JVM для хранения константных литералов String. Стек или куча? Поскольку это литерал, который не связан ни с одним экземпляром, я предполагаю, что он будет храниться в стеке. Но если на него не ссылается ни один экземпляр, литерал должен быть собран с помощью запуска GC (поправьте меня, если я ошибаюсь), так как это обрабатывается, если он хранится в стеке?
104
Ответы:
Технически ответ отрицательный. Согласно спецификации виртуальной машины Java, область для хранения строковых литералов находится в пуле констант времени выполнения . Область памяти пула констант времени выполнения выделяется для каждого класса или интерфейса, поэтому она вообще не привязана к каким-либо экземплярам объекта. Пул констант времени выполнения - это подмножество области методов, в которой «хранятся структуры для каждого класса, такие как пул констант времени выполнения, данные полей и методов, а также код для методов и конструкторов, включая специальные методы, используемые при инициализации классов и экземпляров и интерфейсе. инициализация типа ". В спецификации виртуальной машины говорится, что хотя область метода логически является частью кучи, он не требует, чтобы память, выделенная в области метода, подвергалась сборке мусора или другому поведению, которое было бы связано с обычными структурами данных, выделенными для кучи.
источник
Как объясняется в этом ответе , точное местоположение пула строк не указано и может варьироваться от одной реализации JVM к другой.
Интересно отметить, что до Java 7 пул находился в перманентном пространстве кучи на JVM горячей точки, но с Java 7 он был перемещен в основную часть кучи :
А в Java 8 Hotspot постоянная генерация была полностью удалена.
источник
Строковые литералы не хранятся в стеке. Никогда. Фактически в стеке не хранятся никакие объекты.
Строковые литералы (или , точнее, объекты строк , которые представляют их)
являютсяисторически хранятся в Heap называется «PermGen» куча. (Пермген - сокращение от постоянного поколения.)В обычных условиях строковые литералы и многое другое в куче permgen доступны «постоянно» и не собираются сборщиком мусора. (Например, строковые литералы всегда доступны из объектов кода, которые их используют.) Однако вы можете настроить JVM для попытки найти и собрать динамически загруженные классы, которые больше не нужны, и это может привести к сборке строковых литералов. .
РАЗЪЯСНЕНИЕ №1 - Я не говорю, что Пермген не получает GC. Обычно это происходит, когда JVM решает запустить полный сборщик мусора. Я хочу сказать, что строковые литералы будут доступны до тех пор, пока доступен код, который их использует, и код будет доступен, пока доступен загрузчик классов, а для загрузчиков классов по умолчанию это означает «навсегда».
УТОЧНЕНИЕ №2. Фактически, Java 7 и более поздние версии используют обычную кучу для хранения пула строк. Таким образом, объекты String, представляющие строковые литералы и внутренние строки, фактически находятся в обычной куче. (Подробнее см. Ответ @ assylias.)
Нет никакой «тонкой линии». Это действительно очень просто:
String
объекты, которые представляют / соответствуют строковым литералам, хранятся в пуле строк.String
объекты, созданныеString::intern
вызовом, хранятся в пуле строк.String
объекты НЕ хранятся в пуле строк.Затем возникает отдельный вопрос о том, где «хранится» пул строк. До Java 7 это была куча permgen. Начиная с Java 7, это основная куча.
источник
Объединение строк
String.intern () в Java 6
String.intern () в Java 7
Значения пула строк собираются сборщиком мусора
источник.
источник
Как объясняют другие ответы, память в Java разделена на две части
1. Стек: один стек создается для каждого потока, и в нем хранятся кадры стека, которые снова хранят локальные переменные, и если переменная является ссылочным типом, то эта переменная относится к области памяти в куче для фактического объекта.
2. Куча: все типы объектов будут создаваться только в куче.
Память кучи снова разделена на 3 части
1. Молодое поколение: магазины объекты , которые имеют короткую жизнь, сама по себе молодое поколение , можно разделить на две категории Иден пространства и Survivor пространства .
2. Старое поколение: храните объекты, которые пережили много циклов сборки мусора и до сих пор используются.
3. Постоянное создание: хранит метаданные о программе, например пул констант времени выполнения.
Пул констант строк относится к области постоянной генерации памяти кучи.
Мы можем увидеть пул констант времени выполнения для нашего кода в байт-коде, используя
javap -verbose class_name
который покажет нам ссылки на методы (#Methodref), объекты классов (#Class), строковые литералы (#String)Вы можете узнать больше об этом в моей статье Как JVM обрабатывает перегрузку и переопределение методов изнутри .
источник
К отличным ответам, которые уже были здесь включены, я хочу добавить кое-что, чего мне не хватает, - иллюстрацию.
Как вы уже знаете, JVM делит выделенную память для программы Java на две части. один - стек, а другой - куча . Стек используется для выполнения, а куча - для хранения. В этой куче памяти JVM выделяет некоторую память, специально предназначенную для строковых литералов. Эта часть кучи памяти называется пулом строковых констант .
Так, например, если вы инициализируете следующие объекты:
Строковые литералы
s1
иs2
перейдут в пул строковых констант, объекты obj1, obj2, obj3 - в кучу. На все они будут ссылаться из стека.Также обратите внимание, что «abc» появится в куче и в пуле строковых констант. Почему так
String s1 = "abc"
иString obj1 = new String("abc")
будет создано? Это связано с тем, чтоString obj1 = new String("abc")
явным образом создается новый и референтно отдельный экземпляр объекта String иString s1 = "abc"
может повторно использовать экземпляр из пула строковых констант, если он доступен. Для более подробного объяснения: https://stackoverflow.com/a/3298542/2811258источник