Нужно ли мне беспокоиться о пуле констант строк?

У меня есть Java-приложение, в котором очень много строк - оно принимает огромное количество больших и разных объектов String.

Нужно ли мне беспокоиться о пуле констант String для памяти и производительности?

Есть ли способ узнать, насколько велик бассейн в любой момент?

для sun jvm используйте jmap -permstat, чтобы узнать, сколько памяти используется интернированными строками

Ron 09.09.2010 21:33
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
1
1 157
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Я думаю, вам следует профилировать свое приложение, как с интернированием, так и без него. Тогда вы точно увидите, каков эффект.

Я не верю, что есть способ увидеть размер пула строковых констант.

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

Так что это не должно вызывать беспокойства, если вы не вставляете все эти строки. Если это станет проблемой, можно будет иметь собственную реализацию Map для хранения этих строк, поэтому вы не используете внутренний механизм.

Я проверил реализацию метода intern (), он является нативным, поэтому не представляется простым измерить потребление памяти или просмотреть содержимое пула.

Вы можете использовать этот флаг для увеличения PermSize, если вам не хватает памяти:

-XX:MaxPermSize=64m
Ответ принят как подходящий

Как сказал Марио, пул констант имеет отношение только к строкам intern () ed и к строкам, которые являются константами в Java-коде (они неявно интернированы).

Но есть еще одно предостережение, которое может относиться к вашему случаю: Метод substring() будет разделять базовый char[] с исходная строка. Итак, образец

  String large = ...                  // read 10k string
  String small = large.substring(...) // extrakt a few chars
  large = null;  // large String object no longer reachable,
                 // but 10k char[] still alive, as long as small lives

может вызвать непредвиденное использование памяти.

Хороший, я не знал этого предостережения. Есть этот конструктор пакета, который принимает char [] в качестве аргумента и содержит сильную ссылку. Так что же делать, если нам действительно нужна копия только подстроки?

Mario Ortegón 10.10.2008 15:20

Строка small = новая строка (large.substring (...))

Dave Cheney 12.10.2008 18:32

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

В Java 1.7 substring () - метод больше не использует тот же char [], вместо этого он копирует подстроку в новый массив, т.е.

public String substring(int beginIndex, int endIndex) {
        if (beginIndex < 0) {
            throw new StringIndexOutOfBoundsException(beginIndex);
        }
        if (endIndex > value.length) {
            throw new StringIndexOutOfBoundsException(endIndex);
        }
        int subLen = endIndex - beginIndex;
        if (subLen < 0) {
            throw new StringIndexOutOfBoundsException(subLen);
        }
        return ((beginIndex == 0) && (endIndex == value.length)) ? this
                : new String(value, beginIndex, subLen);
    }

который все для конструктора String, если beginIndex не равен нулю или endIndex не равен длине массива char [].

public String(char value[], int offset, int count) {
        if (offset < 0) {
            throw new StringIndexOutOfBoundsException(offset);
        }
        if (count < 0) {
            throw new StringIndexOutOfBoundsException(count);
        }
        // Note: offset or count might be near -1>>>1.
        if (offset > value.length - count) {
            throw new StringIndexOutOfBoundsException(offset + count);
        }
        this.value = Arrays.copyOfRange(value, offset, offset+count);
    }

Другие вопросы по теме