Что такое пул строк java
Перейти к содержимому

Что такое пул строк java

  • автор:

Что такое пул строк Java?

Как следует из названия, пул строк в Java — это пул строк, хранящихся в памяти кучи Java. Мы знаем, что String — это особый класс в java, и мы можем создавать объекты String, используя оператор new, а также предоставляя значения в двойных кавычках.

Пул строк в Java

package com.journaldev.util; public class StringPool < /** * Java String Pool example * @param args */ public static void main(String[] args) < String s1 = "Cat"; String s2 = "Cat"; String s3 = new String("Cat"); System.out.println("s1 == s2 :"+(s1==s2)); System.out.println("s1 == s3 :"+(s1==s3)); >> 

Вывод вышеуказанной программы:

s1 == s2 :true s1 == s3 :false 

Рекомендуем прочитать: класс Java String

Сколько строк создается в пуле строк?

Иногда на java-интервью вам задают вопрос о пуле строк. Например, сколько строк создается в приведенном ниже выражении;

String str = new String("Cat"); 

В приведенном выше выражении будет создана либо 1, либо 2 строки. Если в пуле уже есть строковый литерал \Cat, то в пуле будет создана только одна строка \str. Если в пуле нет строкового литерала \Cat, то он будет сначала создан в пуле, а затем в пространстве кучи, поэтому всего будет создано 2 строковых объекта. Читайте: Java String Interview Questions

Главная

Пул строк — это конкретная реализация JVM концепции string interning.

Когда мы используем двойные кавычки для создания строки, сначала ищется строка в пуле с таким же значением, если находится, то просто возвращается ссылка, иначе создается новая строка в пуле, а затем возвращается ссылка .
Пул строк возможен исключительно благодаря неизменяемости строк в Java и реализации идеи интернирования строк. Пул строк также является примером паттерна Приспособленец (Flyweight).
когда мы используем оператор new , мы принуждаем класс String создать новый объект строки, а затем мы можем использовать метод intern() для того, чтобы поместить строку в пул, или получить из пула ссылку на другой объект String с таким же значением.

Когда метод intern() вызван, если пул строк уже содержит строку, эквивалентную к нашему объекту, что подтверждается методом equals (Object), тогда возвращается ссылка на строку из пула. В противном случае объект строки добавляется в пул и ссылка на этот объект возвращается.

Сборка мусора :

До Java 7 , пул Java String помещался в пространство PermGen , которое имеет фиксированный размер — его нельзя развернуть во время выполнения и не подходит для сборки мусора .
Риск интернирования строк в PermGen (вместо кучи ) заключается в том, что мы можем получить ошибку OutOfMemory от JVM, если интернируем слишком много строк .

Начиная с Java 7, пул Java String хранится в пространстве Heap , собираемым JVM . Преимущество этого подхода заключается в уменьшении риска ошибки OutOfMemory, поскольку строки, на которые нет ссылок, будут удалены из пула, тем самым освобождая память.

работа пула строк :
 public class MyStringPool < public static void main(String[] args) < String s1 = "Cat"; // создаем строку и помещаем ее в pool строк String s2 = "Cat"; // создаем строку и помещаем ее в pool строк String s3 = new String("Cat"); // создаем новый обьект (не помещаем его в pool) System.out.println("s1 == s2 :"+(s1==s2)); System.out.println("s1 == s3 :"+(s1==s3)); > > s1 == s2 :true s1 == s3 :false 
*.intern() :
 String str1 = "first"; String str2 = "first"; String str3 = new String("first"); str3 = str3.intern(); System.out.println(str1 == str2); System.out.println(str2 == str3); System.out.println(str1 == str3); true true true 
Полезные ссылки:
  • «str».intern() in JavaDoc (Java 8)
  • «str».intern() in JavaDoc (Java 7)
  • «str».intern() in JavaDoc (Java 6)

Руководство по пулу строк Java

Объект String является наиболее часто используемым классом в языке Java.

В этой быстрой статье мы рассмотрим пул строк Java — специальную область памяти, в которой JVM хранит строки .

2. Стажировка строк

Благодаря неизменности строк в Java, JVM может оптимизировать объем выделяемой для них памяти, сохраняя в пуле только одну копию каждой литеральной строки . Этот процесс называется интернированием .

Когда мы создаем переменную String и присваиваем ей значение, JVM ищет в пуле строку с равным значением.

Если он найден, компилятор Java просто вернет ссылку на свой адрес памяти, не выделяя дополнительной памяти.

Если он не найден, он будет добавлен в пул (интернирован), и его ссылка будет возвращена.

Давайте напишем небольшой тест, чтобы проверить это:

 String constantString1 = "ForEach";   String constantString2 = "ForEach";    assertThat(constantString1)   .isSameAs(constantString2); 

3. Строки , выделенные с помощью конструктора

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

Каждая строка , созданная таким образом, будет указывать на другую область памяти со своим собственным адресом.

Давайте посмотрим, чем это отличается от предыдущего случая:

 String constantString = "ForEach";   String newString = new String("ForEach");    assertThat(constantString).isNotSameAs(newString); 

4. Строковый литерал против строкового объекта

Когда мы создаем объект String с помощью оператора new() , он всегда создает новый объект в куче памяти. С другой стороны, если мы создадим объект, используя синтаксис строкового литерала, например, « ForEach », он может вернуть существующий объект из пула строк, если он уже существует. В противном случае он создаст новый объект String и поместит его в пул строк для повторного использования в будущем.

На высоком уровне оба являются объектами String , но основное различие заключается в том, что оператор new() всегда создает новый объект String . Кроме того, когда мы создаем строку , используя литерал, она интернируется.

Это станет намного яснее, если мы сравним два объекта String , созданные с использованием литерала String и оператора new :

 String first = "ForEach";   String second = "ForEach";   System.out.println(first == second); // True 

В этом примере объекты String будут иметь одну и ту же ссылку.

Далее создадим два разных объекта с помощью new и проверим, что у них разные ссылки:

 String third = new String("ForEach");   String fourth = new String("ForEach");   System.out.println(third == fourth); // False 

Точно так же, когда мы сравниваем литерал String с объектом String, созданным с помощью оператора new() с помощью оператора ==, он вернет false:

 String fifth = "ForEach";   String sixth = new String("ForEach");   System.out.println(fifth == sixth); // False 

В общем, мы должны использовать литеральную нотацию String , когда это возможно . Его легче читать, и он дает компилятору возможность оптимизировать наш код.

5. Стажировка вручную

Мы можем вручную интернировать строку в пуле строк Java, вызвав метод intern() для объекта, который мы хотим интернировать.

Интернирование строки вручную сохранит ее ссылку в пуле, и JVM вернет эту ссылку при необходимости.

Давайте создадим тестовый пример для этого:

 String constantString = "interned ForEach";   String newString = new String("interned ForEach");    assertThat(constantString).isNotSameAs(newString);    String internedString = newString.intern();    assertThat(constantString)   .isSameAs(internedString); 

6. Сбор мусора

До Java 7 JVM помещала Java String Pool в пространство PermGen , которое имеет фиксированный размер — его нельзя расширить во время выполнения и нельзя использовать для сборки мусора .

Риск интернирования Strings в PermGen (вместо Heap ) заключается в том, что мы можем получить ошибку OutOfMemory от JVM, если интернируем слишком много Strings .

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

7. Производительность и оптимизация

В Java 6 единственная оптимизация, которую мы можем выполнить, — это увеличение пространства PermGen во время вызова программы с параметром JVM MaxPermSize :

 -XX:MaxPermSize=1G 

В Java 7 у нас есть более подробные параметры для проверки и расширения/уменьшения размера пула. Рассмотрим два варианта просмотра размера пула:

 -XX:+PrintFlagsFinal 
 -XX:+PrintStringTableStatistics 

Если мы хотим увеличить размер пула с точки зрения сегментов, мы можем использовать параметр StringTableSize JVM:

 -XX:StringTableSize=4901 

До Java 7u40 размер пула по умолчанию составлял 1009 сегментов, но в более поздних версиях Java это значение претерпело некоторые изменения. Если быть точным, размер пула по умолчанию от Java 7u40 до Java 11 составлял 60013, а теперь он увеличился до 65536.

Обратите внимание, что увеличение размера пула потребует больше памяти, но имеет то преимущество, что сокращает время, необходимое для вставки строк в таблицу.

8. Примечание о Java 9

До Java 8 строки были внутренне представлены как массив символов — char[] , закодированный в UTF-16 , так что каждый символ использует два байта памяти.

В Java 9 предоставляется новое представление, называемое компактными строками. Этот новый формат выберет подходящую кодировку между char[] и byte[] в зависимости от сохраненного содержимого.

Поскольку новое представление String будет использовать кодировку UTF-16 только при необходимости, объем памяти кучи будет значительно меньше, что, в свою очередь, приведет к меньшим накладным расходам сборщика мусора на JVM.

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

В этом руководстве мы показали, как JVM и компилятор Java оптимизируют выделение памяти для объектов String через Java String Pool.

Все примеры кода, использованные в статье, доступны на GitHub .

Что такое пул строк в Java?

Что такое пул строк в Java?

Пул строк (String Pool) — это множество строк в кучи (Java Heap Memory). Мы знаем, что String — особый класс в java, с помощью которого мы можем создавать строковые объекты.

На диаграмме ниже мы видим как именно строковый пул расположен в памяти Java Heap. И как разные способы создания строк влияют на расположение их в памяти.

String Pool Java Javadevblog.com

Сам строковый пул возможен только потому, что строки в Java неизменные. Также пул строк позволяет сохранить память в Java Runtime, хотя это и требует больше времени на создание самой строки.

Пример работы с пулом строк

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

Однако использование оператора new заставляет класс String создать новый объект String. После этого можем использовать метод intern() , чтобы поместить этот объект в пул строк или обратиться к другому объекту из пула строк, который имеет такое же значение.

Ниже приведена программа, которая демонстрирует работу с пулом строк:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *