«1. Введение

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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