Линейный пул строк и строковый объект Java String
Я знал, что JVM поддерживает пул строковых литералов, чтобы повысить производительность и поддерживать JVM-память, и узнал, что строковый литерал поддерживается в пуле строк. Но я хочу прояснить что-то, связанное с пулом строк и строковым объектом, созданным в куче.
Пожалуйста, исправьте меня, если мое объяснение неверно.
String s = "abc";
Если приведенная выше строка выполнена, строковый литерал "abc" добавляется в пул строк, если он не существует в пуле. И строковый объект создается в куче, а ссылка s
указывает на литерал в пуле.
Вопросы:
- Этот код создает строковый объект в куче каждый раз, когда он выполняется?
- Поддерживает ли пул строковых литералов только строковые литералы или поддерживает строковый объект?
- Когда JVM решает, что ему нужно добавить строковый литерал в пул строк? он принимает решение во время компиляции или времени выполнения?
Я не уверен, где именно создается строковый объект, если он указывает на строковый литерал в пуле.
Спасибо.
Ответы
Ответ 1
Нет "литерального пула". Interned Strings - это обычные объекты кучи. Они могут оказаться в Перминге, но даже тогда они могут быть собраны в мусор.
Файл класса имеет постоянный пул, который содержит литералы String, используемые в классе. Когда класс загружается, из этих данных создаются объекты String, которые, вероятно, очень похожи на то, что делает String # intern.
Этот код создает строковый объект в куче каждый раз, когда он выполняется?
Нет. Будет использоваться один объект String, который будет повторно использоваться. Он был создан при загрузке класса.
Поддерживает ли пул строковых литералов только строковые литералы или поддерживает строковый объект?
Вы также можете ставить строки. Я предполагаю, что к ним относятся более или менее одинаковые.
Когда JVM решает, что ему нужно добавить строковый литерал в пул строк? он принимает решение во время компиляции или времени выполнения?
Литералы всегда "объединены". Другие строки должны иметь "стажер". Таким образом, решение принимается во время компиляции.
Ответ 2
Цитата документации для String.intern() (выделение мое)
Все литералы и строковые константные выражения интернированы. Строковые литералы определены в §3.10.5 языка Java Спецификация
Пул строк, первоначально пустой, поддерживается конфиденциально class String.
При вызове метода intern, если пул уже содержит строка, равная этому объекту String, определяемая равными (Object) метод, то возвращается строка из пула. В противном случае это Объект String добавляется в пул и ссылка на эту строку объект возвращается.
Таким образом,
Этот код создает строковый объект в куче каждый раз, когда он выполняется?
Для каждой уникальной интернированной строки создается только один объект. Все ссылки разделяют этот неизменный объект.
Поддерживает ли строковый литерал только строковые литералы или поддерживает строковый объект?
Нет "Литеральных объектов". Буквенные строковые выражения при преобразовании сохраняются как обычные объекты String
. Также пул содержит все интернированные строковые объекты. Оба неявные (с использованием выражения строкового литерала) и явные (путем вызова .intern()
объекта String
).
Когда JVM решает, что ему нужно добавить строковый литерал в строку бассейн? он принимает решение во время компиляции или времени выполнения?
Я не уверен.
Ответ 3
Я думаю, что есть что-то фундаментальное, чего вам не хватает: в пуле интернированных строк есть только объекты String. Литералы - это не какой-то особый объект; во время выполнения это еще один объект String.
Кроме того, вы можете ставить любой String, который вы хотите, используя String.intern()
; это не должно происходить из литерала.
Так что в отношении ваших вопросов:
- Нет, при загрузке класса будет выделен один объект String.
- Он не поддерживает никаких литералов, а скорее объектов String, которые были интернированы. Обычно они исходят из литералов, но на самом деле это может быть любое постоянное выражение времени компиляции (
String constant = "abc" + "def"
приведет к одному объекту String "abcdef" во время выполнения).
- Они скомпилированы в файл класса. Поэтому они решаются во время компиляции, но, очевидно, сами объекты создаются во время выполнения.
Ответ 4
Этот код создает строковый объект в куче каждый раз, когда он выполняется?
Неа. После создания в литеральном пуле. То же самое повторяется снова и снова.
Поддерживает ли строковый литерал только строковые литералы или поддерживает строковый объект?
Все объекты являются объектами, но объекты, созданные с помощью назначения, помещаются в пул, где объект, созданный с помощью оператора new
, помещается в кучу.
Когда JVM решает, что ему нужно добавить строковый литерал в пул строк? он принимает решение во время компиляции или времени выполнения?
Всякий раз, когда JVM встречается с выражениями типа
String str="Hello"; (string literal) or
String str="Hel" + "lo"; (string constant expression).
и результирующая строка (str
в этом случае) не является пулом, то во всех таких случаях она добавляет новую строку в пул. Этот курс происходит во время выполнения.
Отметьте эту ссылку.