Перейти к основному содержимому

Где живет пул строковых констант Java, куча или стек?

· 3 мин. чтения

1. Введение

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

В этом руководстве мы рассмотрим различные параметры и узнаем, какая область является наиболее подходящей для хранения пула констант String .

2. Пул строковых констант

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

Пул констант String использует в своей реализации Hashmap . Каждое ведро Hashmap содержит список String с одинаковым хеш-кодом. В более ранних версиях Java область хранения для пула имела фиксированный размер и часто могла приводить к ошибке « Не удалось зарезервировать достаточно места для кучи объектов » .

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

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

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

Стек хранит данные в смежных блоках памяти и допускает произвольный доступ. Если классу требуется случайная строка из пула, она может быть недоступна из-за правила стека LIFO (последним пришел — первым ушел). Напротив, куча динамически выделяет память и позволяет нам получать доступ к данным любым способом.

Предположим, у нас есть фрагмент кода, состоящий из разных типов переменных. В стеке будет храниться значение литерала int и ссылки на объекты String и Demo . Значение любого объекта будет храниться в куче, а все строковые литералы помещаются в пул внутри кучи:

./3130e306083c1a9df3ffcf99f0a5854e.png

Переменные, созданные в стеке, освобождаются, как только поток завершает выполнение. Напротив, сборщик мусора восстанавливает ресурсы в куче. Точно так же сборщик мусора собирает элементы, на которые нет ссылок, из пула.

Размер пула по умолчанию может отличаться на разных платформах. В любом случае, он все равно намного больше доступного размера стека. До JDK 7 пул был частью пространства permgen, а начиная с JDK 7 и до сих пор он является частью основной памяти кучи.

3. Заключение

В этой короткой статье мы узнали об области хранения для пула констант String . Стек и куча имеют разные характеристики для хранения данных и доступа к ним. От выделения памяти до ее доступа и доступности куча является наиболее подходящей областью для хранения пула констант String.

На самом деле пул никогда не был частью стековой памяти.