Где живёт постоянный пул Java String, куча или стек?

Я знаю концепцию пула констант и пула констант String, используемых JVM для обработки литералов String. Но я не знаю, какой тип памяти используется JVM для хранения константных литералов String. Стек или куча? Поскольку это литерал, который не связан ни с одним экземпляром, я предполагаю, что он будет храниться в стеке. Но если он не ссылается ни на один экземпляр, литерал должен быть собран прогоном GC (поправьте меня, если я ошибаюсь), так как это обрабатывается, если он хранится в стеке?

91 голос | спросил Rengasami Ramanujam 7 FebruaryEurope/MoscowbMon, 07 Feb 2011 08:48:08 +0300000000amMon, 07 Feb 2011 08:48:08 +030011 2011, 08:48:08

5 ответов


0

Ответ технически ни на что. Согласно Спецификации виртуальной машины Java, область для хранения строковых литералов находится в постоянный пул времени выполнения . Область памяти пула констант времени выполнения выделяется для каждого класса или интерфейса, поэтому она вообще не привязана ни к одному экземпляру объекта. Пул констант времени выполнения - это подмножество области методов , в котором «хранятся структуры каждого класса, такие как пул констант времени выполнения, данные полей и методов, а также код для методов и конструкторов, включая специальные используемые методы. в инициализации класса и экземпляра и инициализации типа интерфейса ". Спецификация виртуальной машины говорит, что хотя область метода логически является частью кучи, она не предписывает, чтобы память, выделенная в области метода, подвергалась сборке мусора или другим действиям, которые были бы связаны с обычными данными. структуры, выделенные для кучи.

ответил Duane Moore 7 FebruaryEurope/MoscowbMon, 07 Feb 2011 09:02:09 +0300000000amMon, 07 Feb 2011 09:02:09 +030011 2011, 09:02:09
0

Как объясняется в этом ответе , точное местоположение пула строк не указано и может отличаться от одной реализации JVM другому.

Интересно отметить, что до Java 7 пул находился в постоянном пространстве кучи на горячей точке JVM, но он был перемещен в основную часть кучи начиная с Java 7 :

  

Область : HotSpot
Синопсис : в JDK 7 встроенные строки больше не выделяются в постоянной генерации кучи Java, а вместо этого - размещается в основной части кучи Java (известной как молодое и старое поколения) вместе с другими объектами, созданными приложением. Это изменение приведет к увеличению объема данных, находящихся в основной куче Java, и уменьшению объема данных в постоянной генерации, что может потребовать корректировки размеров кучи. Большинство приложений увидят только относительно небольшие различия в использовании кучи из-за этого изменения, но более крупные приложения, которые загружают много классов или интенсивно используют метод String.intern (), увидят более существенные различия.   RFE: 6962931

А в Java 8 Hotspot постоянное поколение полностью удалено.

ответил assylias 7 Jpm1000000pmMon, 07 Jan 2013 14:33:50 +040013 2013, 14:33:50
0

Объединение строк

  

Объединение строк (иногда также называемое канонизацией строк)   процесс замены нескольких объектов String равным значением, но   другая идентичность с одним общим объектом String. Вы можете достичь   эта цель, сохраняя свою собственную карту (возможно, софт   или слабые ссылки в зависимости от ваших требований) и использование карты   значения как канонизированные значения. Или вы можете использовать метод String.intern ()   который предоставлен вам JDK.

     

Во время Java 6 использование String.intern () было запрещено многими   стандарты из-за высокой возможности получить исключение OutOfMemoryException, если   объединение вышло из-под контроля. Oracle Java 7 реализация строки   пул был значительно изменен. Вы можете посмотреть детали в    http://bugs.sun.com/view_bug.do?bug_id=6962931 а также    http://bugs.sun.com/view_bug.do?bug_id=6962930 .

String.intern () в Java 6

  

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

     

Самой большой проблемой с таким пулом строк в Java 6 было его расположение -   ПермГен. PermGen имеет фиксированный размер и не может быть расширен в   во время выполнения. Вы можете установить его, используя опцию -XX: MaxPermSize = 96m. Насколько я   знаете, размер PermGen по умолчанию варьируется от 32M до 96M в зависимости от   Платформа. Вы можете увеличить его размер, но его размер все равно будет   фиксированный. Такое ограничение требовало очень осторожного использования String.intern -   вам лучше не проводить никакого неконтролируемого пользовательского ввода, используя этот метод.   Вот почему пулы строк во времена Java 6 были в основном реализованы в   карты, управляемые вручную.

String.intern () в Java 7

  

Инженеры Oracle сделали чрезвычайно важное изменение в строке   логика пула в Java 7 - пул строк был перемещен в кучу.   Это означает, что вы больше не ограничены отдельным фиксированным размером   область памяти. Все строки теперь находятся в куче, как и большинство других   обычные объекты, что позволяет управлять только размером кучи, а   настройка вашего приложения. Технически, одного этого может быть достаточно   причина пересмотреть использование String.intern () в ваших программах на Java 7.   Но есть и другие причины.

Значения пула строк собирают мусор

  

Да, все строки в пуле строк JVM пригодны для мусора   коллекция, если нет ссылок на них из корней вашей программы.   Это относится ко всем обсуждаемым версиям Java. Это означает, что если ваш   интернированная строка вышла из области видимости и других ссылок на   это - это будет сборщик мусора из пула строк JVM.

     

Право на сборку мусора и проживание в куче, JVM   пул струн кажется подходящим местом для всех ваших струн, не так ли?   Теоретически это правда - неиспользуемые строки будут собирать мусор из   пул, используемые строки позволят вам сэкономить память на тот случай, если вы   получить равную строку из ввода. Кажется, идеальное воспоминание   стратегия сохранения? Почти так. Вы должны знать, как пул строк   осуществляется до принятия каких-либо решений.

источник.

ответил Trying 28 42013vEurope/Moscow11bEurope/MoscowThu, 28 Nov 2013 16:23:07 +0400 2013, 16:23:07
0

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

Как вы уже знаете, JVM делит выделенную память для Java-программы на две части. один - стек , а другой - куча . Стек используется для целей выполнения, а куча - для целей хранения. В этой кучной памяти JVM выделяет некоторую память, специально предназначенную для строковых литералов. Эта часть динамической памяти называется пул строковых констант .

Например, если вы инициируете следующие объекты:

String s1 = "abc"; 
String s2 = "123";
String obj1 = new String("abc");
String obj2 = new String("def");
String obj3 = new String("456);

Строковые литералы 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

 введите описание изображения здесь

ответил Stas 25 J000000Tuesday17 2017, 12:29:48
0

Как объясняют другие ответы, память на Java делится на две части

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

2. Куча: все виды объектов будут создаваться только в куче.

Память кучи снова разделена на 3 части

1. Young Generation: . Хранит объекты с коротким сроком службы. Сам Young Generation можно разделить на две категории: Eden Space и Survivor Space .

2. Старое поколение: храните объекты, которые пережили много циклов сборки мусора и на которые все еще ссылаются.

3. Постоянное поколение: хранит метаданные о программе, например, постоянный пул времени выполнения.

Пул строковых констант принадлежит области постоянной генерации памяти кучи.

Как описано в Как работает JVM Внутренняя перегрузка и переопределение метода . Мы можем увидеть пул констант времени выполнения для нашего кода в байт-коде, используя javap -verbose class_name, который покажет ссылки на методы us (#Methodref), объекты класса (#Class), строковые литералы (#String)

 runtime-constant-pool

ответил Naresh Joshi 17 FebruaryEurope/MoscowbSat, 17 Feb 2018 15:53:04 +0300000000pmSat, 17 Feb 2018 15:53:04 +030018 2018, 15:53:04

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132