строковые литералы и сборщик мусора в Java

1

Чтобы быть более конкретным, я прочитал, что в java 7 строковый литерал теперь хранится в основной части кучи, поэтому они становятся подходящими для сборщика мусора?

String a ="z";
a = null;

Теперь объект "z" получает сбор мусора или все еще находится в пуле строк как анонимный объект?

  • 0
    Нет. Строковые литералы не будут собирать мусор.
Теги:
garbage-collection

2 ответа

1

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

Пример:

public interface I {
    String getString();
}

public class Test2 implements I {
    String s = "X";
    @Override
    public String getString() {
        return s;
    }
}

public class Test implements I {
    String s = "X";
    @Override
    public String getString() {
        return s;
    }
}

public class Test1 {

    public static void main(String[] args) throws Exception {
        ClassLoader cl = new URLClassLoader(new URL[] {new URL("file:d:/test/")});
        I i = (I)cl.loadClass("Test").newInstance();
        WeakReference w = new WeakReference(i.getString()); //weak ref to "X" literal
        i = null;
        cl = null;
        System.out.println(w.get());
        System.gc();
        Thread.sleep(1000);
        System.out.println(w.get());
    }
}

скомпилируйте эти классы, переместите Test.class в d: /test, чтобы загрузчик системного класса не смог его увидеть, затем запустите main. Ты увидишь

X
null

что означает, что "X" был GC ed

0
  • Эквивалентные литералы строк (даже те, которые хранятся в отдельных классах в отдельных пакетах) будут относиться к одному и тому же объекту String.

  • В общем, струнные литералы не имеют права на сбор мусора. Когда-либо.

  • Строки, созданные во время выполнения, всегда будут отличаться от строк, созданных из String Literals.

  • Вы можете повторно использовать литералы String со строками времени исполнения, используя метод intern().

  • Лучший способ проверить равенство строк - использовать метод equals().

Источник:
http://www.javaranch.com/journal/200409/ScjpTipLine-StringsLiterally.html

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

Объекты String хранят свои данные в массиве символов. Когда вы берете подстроку строки, вызывая метод substring(), то создаваемый новый объект String не копирует часть данных исходной строки. Вместо этого он сохраняет ссылку на базовые данные исходной строки вместе со смещением и длиной, чтобы указать, какая часть старой строки представляет новый объект String.

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

Чтобы предотвратить эту неэффективность памяти, вы можете явно создать новый объект String с помощью объекта подстроки. Этот второй новый объект String будет копировать данные из объекта подстроки, а только часть, которая вам нужна. просмотреть прозрачность? Примечание. Текстовое содержимое в блоках кода автоматически переносится словами

// Suppose this contains 100K characters read from a file  
String largeString = ...;  

// This will refer to the 100K char array from largeString, keeping the whole buffer in memory  
// even though sub represents only 20 characters  
String sub = largeString.substring(80, 100);  

// This will copy the 20 characters from sub into a new buffer, so that the whole 100K buffer doesn't need to be kept  
String sub2 = new String(sub);  

Если вы хотите увидеть, как именно это работает, посмотрите на исходный код класса String, который вы можете найти в файле src.zip в каталоге установки JDK.

Источник:
http://www.coderanch.com/t/542489/java/java/string-literal-String-Object

  • 0
    Вы должны перестать основывать ответы на древних статьях. Статье javaranch исполнилось десять лет, когда вы написали свой ответ, и она была неправильной, даже когда она была новой, поскольку строковые литералы могут собирать мусор, когда все классы, ссылающиеся на них, становятся недоступными. Статье Coderanch всего семь лет, и она была действительной на момент публикации, но устарела, когда вы опубликовали свой ответ; начиная с Java 7, обновление 6, подстроки больше не разделяют массив с исходной строкой. С другой стороны, String созданная с помощью конструктора String(String) , делит массив с исходной строкой…

Ещё вопросы

Сообщество Overcoder
Наверх
Меню