Является ли Java String Intern мухой?

Выполняется ли реализация пула памяти Java String в виде мухи?

Почему у меня есть это сомнение, я вижу, что в Интернате нет внешнего государства. В GoF я читал, что должен быть правильный баланс между внутренним и внешним состоянием. Но в интернатуре все неотъемлемо.

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

Пожалуйста, помогите мне понять.

Ответ 1

Независимо от интернирования, Java String использует мухи-паттерн, разделяя char[] между строкой и данными, полученными из нее через substring и аналогичные вызовы методов. Однако это имеет обратную сторону: если вы берете небольшую подстроку огромной строки, огромный char[] не будет иметь права на сбор мусора.

Примечание. по OpenJDK версии 1.7.0_06 выше устарело: код был изменен, так что char[] больше не разделяется между экземплярами. substring() создает новый массив.

Ответ 2

Да реализация String.intern() следует за мухомором.

Как javadoc говорит

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

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

Отсюда следует, что для любых двух строк s и t s.intern() == t.intern() истинно тогда и только тогда, когда истинны s.equals(t).

Все литералы и строковые константные выражения интернированы. Строковые литералы определены в §3.10.5 языка Java Спецификация

Внутренние строки находятся в пространстве "Perm Gen", а на строковых объектах, возвращаемых .intern(), вы можете использовать оператор ==, потому что .intern() всегда возвращает одинаковый объект для равных значений.

Тогда помните, что метод .intern() не создает утечек, потому что JVM сегодня может мусор пула.

Попробуйте прочитать эту статью.

Ответ 3

Вы правильно определили, что Interning и Flyweight основаны на одной и той же идее: кэширование и совместное использование общего состояния.

С Flyweight, в крайнем случае, когда нет внешнего состояния для хранения, остается только указатель на внутреннее состояние. Тогда нет необходимости, чтобы внешнее состояние было даже объектом, сам указатель может быть внешним состоянием. Это когда Flyweight стал стажером.

Является ли Interning "действительно" своего рода Flyweight или нет, это просто дискуссия по поводу определений. Самое важное - это понимание того, как одного можно рассматривать как специализированный экземпляр другого, так что ты в порядке.

Ответ 4

Как и другие, String.intern() все о кешировании. Он возвращает ссылку на уже сохраненный строковый литерал в пуле. Таким образом, это как-то похоже на flyweight pattern, так как использует существующие объекты, что приводит к снижению потребления памяти и увеличению производительности (хотя у статора также есть собственные служебные накладные расходы в пуле строк). Следовательно, эти два могут казаться похожими, но на самом деле их нет.

Ответ 5

Нет, совместного использования объектов для уменьшения памяти недостаточно для того, чтобы называть это наименьшим весом. Другими словами, кеширование не является автоматическим шаблоном.

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

Несколько комментариев в этой теме стоит повторить, потому что они кратко отвечают на общий вопрос.

  • Если для ваших объектов нет внешнего контекста, вы просто кешируете. Причина, по которой шаблон Flyweight полезен даже для определения, заключается в том, что люди часто забывают, что они могут по крайней мере кэшировать часть объекта, которая не зависит от контекста, и делиться ею.

    --C S

  • Flyweight - это разделение внутренних объектов. Стажировка - это просто кеширование целых объектов.

    --Marko Топольник

Но давайте сравним интернирование String с критериями, определенными GoF (на странице 197).

Примените шаблон Flyweight, когда все из следующего верно:

  • Приложение использует большое количество объектов.
  • Стоимость хранения высока из-за огромного количества предметов.
  • Большая часть состояния объекта может быть сделана внешней.
  • Многие группы объектов могут быть заменены на относительно немного общих объектов после удаления внешнего состояния.
  • Приложение не зависит от идентичности объекта. Поскольку объекты flyweight могут использоваться совместно, тесты идентичности будут возвращать true для концептуально различных объектов.
  1. Очевидно, что во многих приложениях используется большое количество строк, поэтому этот критерий проходит.
  2. Хранение строк стоит дорого, по крайней мере, по сравнению с примитивными типами, поэтому давайте дадим этот критерий.
  3. Вот где мы запутались: ни одно из строкового состояния не становится внешним. Этот критерий не выполняется.
  4. Если мы великодушны и игнорируем часть о внешнем состоянии, мы могли бы также пройти этот критерий, поскольку строки, как правило, используются повторно.
  5. Любой, кто когда-либо использовал == для сравнения строк в Java, знает, что он не зависит от идентичности объекта, поэтому этот критерий проходит.

Ну, критерии прохождения 4/5 довольно хороши, верно? Разве этого не достаточно, чтобы сказать, что стажировка/кеширование и похудение одинаковы? Нет, похоже! Акцент на слове все в цитате GoF их, а не мое. Естественно, существует сильное желание пометить как можно больше реализаций именами шаблонов GoF, потому что это придает легитимность этим реализациям. (Наиболее вопиющие случаи - это фабричные шаблоны, которые вы можете легко найти, маркируя каждый вид творческого кода, который только можно себе представить; но я отступаю.) Если шаблоны не привязаны к опубликованным определениям, они перекрываются и теряют смысл, побеждая большую часть их цель (общий словарь).

И, наконец, давайте проанализируем первое предложение главы по наименьшему весу: что определяет GoF как Намерение шаблона с наименьшим весом.

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

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

Очевидно, что есть сходство между интернированием/кэшированием строк и шаблоном Flyweight; но они не одинаковы.

Ответ 6

Вес "мухи" - это разделение внутренних объектов объекта immmutables. Interning просто кэширует все объекты.