Чтобы быть более конкретным, я прочитал, что в java 7 строковый литерал теперь хранится в основной части кучи, поэтому они становятся подходящими для сборщика мусора?
String a ="z";
a = null;
Теперь объект "z" получает сбор мусора или все еще находится в пуле строк как анонимный объект?
Строковые литералы могут быть только 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
Эквивалентные литералы строк (даже те, которые хранятся в отдельных классах в отдельных пакетах) будут относиться к одному и тому же объекту 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
String
созданная с помощью конструктора String(String)
, делит массив с исходной строкой…