Как устроен пул строк в Java
Что проверяют
Знаете ли вы, где физически живёт пул, чем литерал отличается от new String() и почему строки сравнивают через equals. Следом часто просят предсказать результат нескольких == и спрашивают, когда intern() вообще стоит вызывать.
Как отвечать
Пул строк это таблица канонических экземпляров String, которую держит JVM. В HotSpot это хеш-таблица StringTable в нативной памяти, а сами объекты строк с Java 7 лежат в обычной куче, до этого они жили в PermGen. Опорные пункты:
- литералы: одинаковые литералы во всех классах указывают на один объект, поэтому для
String a = "Hello"иString b = "Hello"выражениеa == bистинно; - константы времени компиляции:
"Hel" + "lo"компилятор склеивает сам, результат тоже попадёт в пул. Склейка с переменной происходит в рантайме и даёт новый объект; new String("Hello"): всегда новый объект в куче, даже если такой литерал уже в пуле;intern(): возвращает канонический экземпляр из пула, а при его отсутствии кладёт туда текущую строку. После этогоnew String("Hello").intern() == "Hello"истинно;- сборка мусора: строки из пула, на которые никто не ссылается, собираются так же, как остальные объекты. Размер таблицы настраивается флагом
-XX:StringTableSize.
Пул работает, потому что String неизменяем: общий экземпляр безопасно отдавать кому угодно. Стоит упомянуть и соседние оптимизации: Compact Strings с Java 9 хранят строки из символов Latin-1 по байту на символ, а -XX:+UseStringDeduplication в G1 убирает дубли массивов внутри разных объектов String, пул при этом не трогая.
Где спотыкаются
Говорят, что пул находится в PermGen. Это верно только для Java 6 и раньше, а в Java 8 PermGen нет вообще.
Советуют сравнивать строки через == ради скорости. Результат зависит от того, откуда пришла строка: строка из JSON или из базы окажется другим объектом. Сравнивают через equals.
Вызывают intern() на всём подряд ради экономии памяти. Каждый вызов это поиск в глобальной таблице, и при миллионах уникальных строк она становится узким местом. Оправдан intern() только на небольшом наборе часто повторяющихся значений.