Когда Java-строки интернированы? - PullRequest
18 голосов
/ 10 августа 2010

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

Я не могу найти никаких доказательств, подтверждающих это. Кто-нибудь может это оправдать?

Ответы [ 2 ]

17 голосов
/ 10 августа 2010

Оптимизация происходит (или, по крайней мере, может происходить) в обоих местах:

  • Если в одном классе появляются две ссылки на одну и ту же строковую константу, я ожидаю, что файл класса будет содержать толькоодна постоянная запись в пуле.Это не строго требуется , чтобы гарантировать, что в JVM создан только один String объект, но это очевидная оптимизация, которую нужно сделать.Это на самом деле не интернирование как таковое - просто постоянная оптимизация.
  • Когда классы загружаются, пул строк для класса добавляется в пул интернирования.Это "настоящий" интернирование.

(у меня есть смутное воспоминание, что один из кусочков работы для Java 7 вокруг "маленьких файлов JAR" включал в себя один строковый пул для всего файла JAR ...... но я могу ошибаться.)

РЕДАКТИРОВАТЬ: Раздел 5.1 спецификации JVM, «Пул постоянных времени выполнения» подробно описывает это:

Для получения строкового литерала виртуальная машина Java проверяет последовательность символов, заданную структурой CONSTANT_String_info.

  • Если метод String.intern ранее вызывался для экземпляра класса Stringсодержащий последовательность символов Unicode, идентичную той, которая задана структурой CONSTANT_String_info, результатом литерального преобразования строки является ссылка на тот же экземпляр класса String.

  • В противном случае новый экземплярсоздается класс String, содержащий последовательность символов Unicode, заданную структурой CONSTANT_String_info;этот экземпляр класса является результатом строкового литерала.Наконец, вызывается метод intern нового экземпляра String.

0 голосов
/ 28 мая 2013

Runtime.

Спецификации JLS и JVM определяют компиляцию javac для файлов классов, которые содержат объявления констант (в пуле констант) и постоянное использование в коде (который javac может встроить как ссылочные значения примитива / объекта).Для констант String во время компиляции компилятор генерирует код для конструирования экземпляров String и вызова для них String.intern (), чтобы JVM автоматически интернировала String константы.Это поведенческое требование от JLS:

http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.28

Постоянные выражения времени компиляции типа String всегда "интернированы", так чтодля совместного использования уникальных экземпляров, используя метод String.intern.

Но в этих спецификациях нет ни концепции, ни определения каких-либо структур / ссылок / дескрипторов / ссылок / внутренних переменных String, будь то время компиляции или время выполнения,(Конечно, в общем, спецификация JVM не требует какой-либо конкретной внутренней структуры для объектов: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.7)

Причина, по которой структуры внутреннего пула не упоминаются, заключается в том, что они полностью обрабатываются с помощью класса String.Внутренний пул является частной статической структурой на уровне класса класса String (не определяется спецификациями JLS & JVM и javadoc).

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...