2009-05-29 3 views
4

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

Являются ли эти два утверждения эквивалентными?

String s1 = ("hello" + "world").intern(); 

String s2 = "hello".intern() + "world".intern(); 

UPDATE

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

public String toAddress(Transport transport) 
{ 
    Constraint.NonNullArgument.check(transport, "transport"); 

    switch(transport) 
    { 
    case GOOGLE: 
    case MSN: 
     return (transport.code() + PERIOD + _domain).intern(); 
    case YAHOO: 
    default: 
     return _domain; 
    } 
} 
private String _domain; // is initialized during constructor 
private static final String PERIOD = "."; 

ответ

10

Лучший совет, о котором я могу думать, - не беспокоить. Статически объявленные String будут в постоянном пуле каким-либо образом, если вы не динамически создаете String, которая ... errr no Я не могу думать о причине.

Я программировал с использованием Java с 97, и я никогда не использовал String.intern().

EDIT: После просмотра вашего обновления я действительно считаю, что вы не должны использовать intern(). Ваш метод выглядит совершенно нормально, и нет причин для использования intern().

Моя причина в том, что она заражает оптимизацию и потенциально преждевременную, при этом вы угадываете сборщик мусора. Если справедливый из вас метод недолговечен, то результирующая строка умрет молодое поколение очень скоро после этого в следующем младшем GC, и если это не будет, он будет интернирован (из-за лучшего слова) в зрелом поколении так или иначе ,

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

+3

Прочитать http://kohlerm.blogspot.com/2009/01/is -javalangstringintern-really-evil.html –

+3

intern() не злой ... вам это не понадобится –

+2

Я программировал на Java уже много лет и только дважды использовал intern(), делая очень топор ü оптимизацию производительности некоторых серверных программ, которые необходимы для поддержки как можно большего количества сеансов. 99.В 99% случаев вы никогда не должны его использовать, и если вы найдете место, где это имеет смысл, обязательно подумайте о влиянии на ваше пространство перменто: вы хотите только ставить небольшие ограниченные наборы литералов. –

2

Я бы сказал, нет. s1 добавляет «helloworld» в пул, тогда как s2 состоит из двух объединенных строк «hello» и «world».

+0

javac делает конкатенацию, так что «helloworld» уже интернирован. –

7

№. Добавление двух интернированных строк вместе не дает вам интернированную строку.

Это говорит о том, что довольно редко нужно «тщательно ставить свои струны». Если вы не имеете дело с огромным количеством идентичных строк, это больше проблем, чем того стоит.

+2

Опять же, javac делает конкатенацию, поэтому что «helloworld» уже интернирован. Используйте javap -c, чтобы увидеть это. –

+0

javac делает первую конкатенацию, но не последнюю. Вопрос был не в том («hello» + «world»). intern() эквивалентен «helloworld». Вопрос в том, соответствует ли эта (интернированная) строка «hello» .intern() + «world» .intern(). Ответ отрицательный, потому что javac не con спрятать последнее выражение в «helloworld» (предположительно из-за вызовов промежуточных методов) и объединить два интернированных объекта String вместе не даст вам интернированную строку. –

10

Как говорит дженсграмма, эти два утверждения не эквивалентны. Два важного правило:

  • Конкатенация строковых литералов в коде заканчивается с строковой константой, так что эти два утверждения является точно эквивалентным (они производят одинаковый байткод):

    String x = "foo" + "bar": 
    String x = "foobar"; 
    
  • Строка константы интернированы автоматически, вам не нужно делать это явно

Теперь это концентрируется на литералы - вы на самом деле, называя intern литералами, или ваш реальный прецедент несколько отличается (например. интернирование значений, полученных из базы данных, которые вы часто увидите)? Если да, пожалуйста, сообщите нам более подробную информацию.

EDIT: Хорошо, основанный на вопрос редактирования: это может сохранить некоторую память если вы в конечном итоге хранения возвращаемого значения toAddress() где-то, что он будет придерживаться вокруг в течение долгого времени и вы в конечном итоге с тем же адресом несколько раз. Если эти не являются случаем, интернинг на самом деле, вероятно, ухудшит ситуацию. Я не знаю точно, будут ли интернированные струны оставаться навсегда, но это вполне возможно.

Мне кажется, что это вряд ли, чтобы быть хорошим использованием интернирования, и, возможно, это будет хуже. Вы упоминаете, что пытаетесь спасти пространство пергмена - почему вы считаете, что интернирование там поможет? Конкатенированные струны все равно не окажутся в пердгене, если я не ошибаюсь.

+0

Прочтите фрагмент моего использования стажера. –

+0

Интернированные струны регенерированы. Они находятся на SUN JVM, хранящемся в permspace, что означает, что они требуют полного GC для исправления. – kohlerm

2

Подробнее поможет нам понять ваш запрос ... В любом случае ...

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

+0

См. Обновленный вопрос для примера использования. –

2

Возможно, вам понадобится какая-то форма доказательства (возможно, через профилирование), что вы «избиваете пространство перменто», прежде чем писать весь свой код.

В противном случае вы можете просто делать «преждевременную оптимизацию», которая, как правило, неодобрительно. См. http://en.wikipedia.org/wiki/Optimization_(computer_science)#When_to_optimize для получения более подробной информации о том, почему это может быть плохо.

0

Во многих случаях «тщательное интернирование» ваших строк не дает вам ничего, кроме некоторого времени. Рассмотрим следующий случай:

void foobar(int x) { 
    String s1 = someMethod(x).intern(); 
    ... 
    ... 
} 

Так s1 интернирован, нет (кучи) пространство не впустую? Неправильно! Скорее всего, промежуточный результат someMethod (x) все еще существует где-то в куче и должен быть собран в мусор. Это потому, что someMethod() каким-то образом построил строку, и (если только он не возвращает литерал), это делало это в куче. Но тогда ... лучше взгляните на то, для чего используется пространство перггенов. Он используется для метаданных о классах и (ooops) таблицы String.intern. Путем интернирования всех ваших строк вы делаете именно то, чего вы хотели избежать: Pummel the permgen space.

Более подробная информация здесь: http://www.thesorensens.org/2006/09/09/java-permgen-space-stringintern-xml-parsing/

0

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

+0

Раньше они были созданы в perm gen (не совсем уверены, что такое текущее состояние). –

+0

Если вы говорите о PermGen, я собираюсь предположить, что вы используете Sun JVM. Могу ли я спросить, какая версия? –

0

интернирование строк в основном утечка памяти чтобы случиться :(

Если у вас есть очень, очень хорошая причина [1] не делают этого, но оставить его на JVM.

[ 1] Как в разделе «Уважаемый босс, пожалуйста, не увольняйте меня. У меня есть данные профилирования, чтобы поддержать мое решение использовать стажера».

Смежные вопросы