«1. Введение
Всякий раз, когда мы объявляем переменную или создаем объект, он сохраняется в памяти. На высоком уровне Java делит память на два блока: стек и кучу. Обе памяти хранят определенные типы данных и имеют разные схемы их хранения и доступа.
В этом уроке мы рассмотрим различные параметры и узнаем, какая область является наиболее подходящей для хранения пула констант String.
2. Пул строковых констант
Пул строковых констант представляет собой специальную область памяти. Когда мы объявляем строковый литерал, JVM создает объект в пуле и сохраняет его ссылку в стеке. Перед созданием каждого объекта String в памяти JVM выполняет несколько шагов, чтобы уменьшить нагрузку на память.
Пул констант String использует в своей реализации Hashmap. Каждое ведро Hashmap содержит список строк с одинаковым хеш-кодом. В более ранних версиях Java область хранения для пула имела фиксированный размер, что часто могло приводить к ошибке «Не удалось зарезервировать достаточно места для кучи объектов».
Когда система загружает классы, строковые литералы всех классов переходят в пул уровня приложения. Это связано с тем, что одинаковые строковые литералы разных классов должны быть одним и тем же объектом. В этих ситуациях данные в пуле должны быть доступны каждому классу без какой-либо зависимости.
Обычно в стеке хранятся недолговечные данные. Он включает в себя локальные примитивные переменные, ссылки на объекты кучи и выполняемые методы. Куча обеспечивает динамическое выделение памяти, сохраняет объекты Java и классы JRE во время выполнения.
Куча обеспечивает глобальный доступ, и хранилища данных в куче доступны для всех потоков в течение всего времени существования приложения, тогда как хранилища данных в стеке имеют частную область действия, и только поток-владелец может получить к ним доступ.
Стек хранит данные в смежных блоках памяти и допускает произвольный доступ. Если классу требуется случайная строка из пула, она может быть недоступна из-за правила стека LIFO (последним пришел — первым ушел). Напротив, куча динамически выделяет память и позволяет нам получать доступ к данным любым способом.
Предположим, у нас есть фрагмент кода, состоящий из переменных разных типов. В стеке будет храниться значение литерала int и ссылки на объекты String и Demo. Значение любого объекта будет храниться в куче, а все строковые литералы помещаются в пул внутри кучи:
Переменные, созданные в стеке, освобождаются, как только поток завершает выполнение. Напротив, сборщик мусора восстанавливает ресурсы в куче. Точно так же сборщик мусора собирает элементы, на которые нет ссылок, из пула.
Размер пула по умолчанию может отличаться на разных платформах. В любом случае, он все равно намного больше доступного размера стека. До JDK 7 пул был частью пространства permgen, а начиная с JDK 7 и до сих пор он является частью основной памяти кучи.
3. Заключение
В этой короткой статье мы узнали о области хранения для пула строковых констант. Стек и куча имеют разные характеристики для хранения данных и доступа к ним. От выделения памяти до ее доступа и доступности куча является наиболее подходящей областью для хранения пула констант String.
На самом деле пул никогда не был частью стековой памяти.