Поведение сборки мусора для String.intern () - PullRequest
22 голосов
/ 12 марта 2010

Если я использую String.intern () для повышения производительности, так как я могу использовать "==" для сравнения интернированной строки, столкнусь ли я с проблемами сборки мусора? Чем механизм сбора мусора интернированных строк отличается от обычных строк?

Ответы [ 4 ]

19 голосов
/ 12 марта 2010

String.intern() управляет внутренним, встроенным пулом, который имеет некоторые специальные функции, связанные с GC. Это старый код, но если бы он был реализован заново, он использовал бы java.util.WeakHashMap. Слабые ссылки - это способ сохранить указатель на объект, не предотвращая его сбор. Как раз то, что нужно для объединяющего пула, такого как интернированные строки.

То, что интернированные строки являются сборщиком мусора, можно продемонстрировать с помощью следующего кода Java:

public class InternedStringsAreCollected {

    public static void main(String[] args)
    {
        for (int i = 0; i < 30; i ++) {
            foo();  
            System.gc();
        }   
    }

    private static void foo()
    {
        char[] tc = new char[10];
        for (int i = 0; i < tc.length; i ++)
            tc[i] = (char)(i * 136757);
        String s = new String(tc).intern();
        System.out.println(System.identityHashCode(s));
    }
}

Этот код создает 30 раз одну и ту же строку, каждый раз интернируя ее. Кроме того, он использует System.identityHashCode(), чтобы показать, какой хэш-код Object.hashCode() вернулся бы в этой интернированной строке. При запуске этот код выводит различные целочисленные значения, что означает, что вы не получаете один и тот же экземпляр каждый раз.

В любом случае, использование String.intern() несколько не рекомендуется. Это общий статический пул, что означает, что он легко превращается в узкое место в многоядерных системах. Используйте String.equals() для сравнения строк, и вы будете жить дольше и счастливее.

11 голосов
/ 12 марта 2010

На самом деле, это не оптимизация сборки мусора, а оптимизация пула строк. Когда вы вызываете <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/String.html#intern()" rel="nofollow noreferrer">String.intern()</a>, вы заменяете ссылку на исходную строку на ее базовую ссылку (ссылку на первую встречу с этой строкой или эту ссылку, если она еще не известна).

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

Как правило, я считаю предпочтительным, чтобы никогда не использовал этот метод intern и позволял компилятору использовать его только для констант Strings, объявленных так:

String myString = "a constant that will be interned";

Это лучше, в том смысле, что оно не позволит вам сделать ложное предположение, == может сработать, если не сработает.

Кроме того, String.equals по сути вызывает == в качестве оптимизации, гарантируя, что внутренняя оптимизация строк используется под капотом. Это еще одно доказательство того, что == не следует никогда использовать в строках.

6 голосов
/ 12 августа 2016

Эта статья дает полный ответ.

В java 6 пул строк находится в PermGen, так как java 7 пул строк находится в памяти кучи.

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

Строка пула - это HashMap с фиксированным размером, который был небольшим в java 6 и ранних версиях java 7, но увеличен до 60013 после java 7u40.
Его можно изменить с помощью -XX: StringTableSize = <новый размер> и просмотреть с помощью -XX: + PrintFlagsFinal параметры Java.

0 голосов
/ 12 марта 2010

Пожалуйста, прочитайте: http://satukubik.com/2009/01/06/java-tips-memory-optimization-for-string/

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

...